• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/bcmalgo.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 #include <stdlib.h>
  3 #include <sys/types.h>
  4 #include <stdio.h>
  5 #include <inttypes.h>
  6 #include <string.h>
  7 #include <getopt.h>
  8 #include <unistd.h>
  9 #include <sys/time.h>
 10 #include <sys/stat.h>
 11 #include "bcmalgo.h"
 12 
 13 
 14 #define UTIL_VERSION "0.1"
 15 #define ENDIAN_REVERSE_NEEDED
 16 
 17 uint32_t reverse_endian32 ( uint32_t data )
 18 {
 19 #ifdef ENDIAN_REVERSE_NEEDED
 20         return 0 | ( data & 0x000000ff ) << 24
 21                | ( data & 0x0000ff00 ) << 8
 22                | ( data & 0x00ff0000 ) >> 8
 23                | ( data & 0xff000000 ) >> 24;
 24 #else
 25         return data;
 26 #endif
 27 }
 28 
 29 uint16_t reverse_endian16 ( uint16_t data )
 30 {
 31 #ifdef ENDIAN_REVERSE_NEEDED
 32         return 0 | ( data & 0x00ff ) << 8
 33                | ( data & 0xff00 ) >> 8;
 34 #else
 35         return data;
 36 #endif
 37 }
 38 
 39 
 40 
 41 uint32_t get_buffer_crc ( char* filebuffer,size_t size )
 42 {
 43 
 44         long crc=0xffffffffL;
 45         long crcxor = 0xffffffffL;
 46         long num4 = 0xffffffffL;
 47         long num5 = size;
 48         long num6 = 0x4c11db7L;
 49         long num7 = 0x80000000L;
 50         int i;
 51         long j;
 52         for ( i = 0; i < ( num5 ); i++ )
 53         {
 54                 long num2 = filebuffer[i];
 55                 for ( j = 0x80L; j != 0L; j = j >> 1 )
 56                 {
 57                         long num3 = crc & num7;
 58                         crc = crc << 1;
 59                         if ( ( num2 & j ) != 0L )
 60                         {
 61                                 num3 ^= num7;
 62                         }
 63                         if ( num3 != 0L )
 64                         {
 65                                 crc ^= num6;
 66                         }
 67                 }
 68         }
 69         crc ^= crcxor;
 70         crc &= num4;
 71 
 72         uint8_t b1 = ( uint8_t ) ( ( crc & -16777216L ) >> 0x18 );
 73         uint8_t b2 = ( uint8_t ) ( ( crc & 0xff0000L ) >> 0x10 );
 74         uint8_t b3 = ( uint8_t ) ( ( crc & 0xff00L ) >> 8 );
 75         uint8_t b4 = ( uint8_t ) ( crc & 0xffL );
 76         int32_t crc_result = ( b1 | b2 << 8| b3 << 16| b4 <<24 );
 77         return reverse_endian32 ( crc_result );
 78 }
 79 
 80 //Thnx to Vector for the algo.
 81 uint32_t get_file_crc ( char* filename )
 82 {
 83         struct stat buf;
 84         stat ( filename,&buf );
 85         char* filebuffer = malloc ( buf.st_size+10 );
 86         FILE* fd = fopen ( filename,"r" );
 87         fread ( filebuffer, 1, buf.st_size,fd );
 88         fclose ( fd );
 89         uint32_t crc = get_buffer_crc ( filebuffer,buf.st_size );
 90         free ( filebuffer );
 91         return crc;
 92 }
 93 
 94 
 95 
 96 uint16_t get_hcs ( ldr_header_t* hd )
 97 {
 98         uint8_t* head = ( uint8_t* ) hd;
 99         uint8_t hcs_minor;
100         uint8_t hcs_major;
101         uint16_t n = 0xffff;
102         int state = 0;
103         int i,j;
104         for ( i = 0; i < 0x54; i++ )
105         {
106                 uint16_t m = head[i];
107                 m = m << 8;
108                 for ( j = 0; j < 8; j++ )
109                 {
110                         if ( ( ( n ^ m ) & 0x8000 ) == 0 )
111                         {
112                                 state = 0;
113                         }
114                         else
115                         {
116                                 state = 1;
117                         }
118                         n = n << 1;
119                         if ( state )
120                         {
121                                 n ^= 0x1021;
122                         }
123                         m = m << 1;
124                 }
125                 n &= 0xffff;
126         }
127         n ^= 0xffff;
128         hcs_major = ( uint8_t ) ( ( n & 0xff00 ) >> 8 );
129         hcs_minor = ( uint8_t ) ( n & 0xff );
130         uint16_t hcs = hcs_major <<8 | hcs_minor;
131         return hcs;
132 }
133 
134 ldr_header_t* construct_header ( uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc_data )
135 {
136         ldr_header_t* hd = malloc ( sizeof ( ldr_header_t ) );
137         hd->magic=reverse_endian16 ( magic );
138         hd->control=0; //FixMe: Make use of it once compression is around
139         hd->rev_min = reverse_endian16 ( rev_min );
140         hd->rev_maj = reverse_endian16 ( rev_maj );
141         hd->build_date = reverse_endian32 ( build_date );
142         hd->filelen = reverse_endian32 ( filelen );
143         hd->ldaddress = reverse_endian32 ( ldaddress );
144         printf ( "Creating header for %s...\n", filename );
145         if ( strlen ( filename ) >63 )
146         {
147                 printf ( "[!] Filename too long - stripping it to 63 bytes.\n" );
148                 strncpy ( ( char* ) &hd->filename, filename, 63 );
149                 hd->filename[63]=0x00;
150         }
151         else
152         {
153                 strcpy ( ( char* ) &hd->filename, filename );
154         }
155         hd->crc=reverse_endian32 ( crc_data );
156         hd->hcs = reverse_endian16 ( get_hcs ( hd ) );
157         return hd;
158 }
159 
160 static char control_unc[]  = "Uncompressed";
161 static char control_lz[]   = "LZRW1/KH";
162 static char control_mlzo[] = "mini-LZO";
163 static char control_nrv[] = "NRV2D99 [Bootloader?]";
164 static char control_nstdlzma[] = "(non-standard) LZMA";
165 static char control_unk[] = "Unknown";
166 char* get_control_info ( uint16_t control )
167 {
168         control = reverse_endian16 ( control );
169         switch ( control )
170         {
171                 case 0:
172                         return control_unc;
173                         break;
174                 case 1:
175                         return control_lz;
176                         break;
177                 case 2:
178                         return control_mlzo;
179                         break;
180                 case 3:
181                         return control_unc;
182                         break;
183                 case 4:
184                         return control_nrv;
185                         break;
186                 case 5:
187                         return control_nstdlzma;
188                         break;
189                 case 6:
190                         return control_unc;
191                         break;
192                 case 7:
193                         return control_unc;
194                         break;
195                 default:
196                         return control_unk;
197                         break;
198         }
199 
200 }
201 
202 int dump_header ( ldr_header_t* hd )
203 {
204         printf ( "=== Header Information ===\n" );
205         printf ( "Header magic:\t0x%04X\n",reverse_endian16 ( hd->magic ) );
206         printf ( "Control:\t0x%04X (%s)\n",reverse_endian16 ( hd->control ), get_control_info ( hd->control ) );
207         printf ( "Major rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_maj ) );
208         printf ( "Minor rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_min ) );
209         printf ( "File name :\t%s\n", ( char* ) &hd->filename );
210         printf ( "File length:\t%d bytes\n", reverse_endian32 ( hd->filelen ) );
211         printf ( "Build time:\t0x%08X //FixMe: print in human-readable form\n", reverse_endian32 ( hd->build_date ) ); //FixMe:
212         printf ( "HCS:\t\t0x%04X  ",reverse_endian16 ( hd->hcs ) );
213         uint16_t hcs = get_hcs ( hd );
214         int ret=0;
215         if ( hcs ==reverse_endian16 ( hd->hcs ) )
216         {
217                 printf ( "(OK!)\n" );
218         }
219         else
220         {
221                 printf ( "(ERROR! expected 0x%04X)\n",hcs );
222                 ret=1;
223         }
224 //printf("HCS:\t0x%02X",reverse_endian32(hd->hcs));
225         printf ( "Load address:\t0x%08X\n", reverse_endian32 ( hd->ldaddress ) ); //FixMe:
226         printf ( "HNW:\t\t0x%04X\n",reverse_endian16 ( hd->her_znaet_chto ) ); //Hell knows what
227         printf ( "CRC:\t\t0x%08X\n",reverse_endian32 ( hd->crc ) );
228         printf ( "=== Binary Header Dump===\n" );
229         int i;
230         uint8_t* head = ( uint8_t* ) hd;
231         for ( i=0;i<=sizeof ( ldr_header_t );i++ )
232         {
233                 if ( i % 8==0 )
234                         printf ( "\n" );
235                 printf ( "0x%02x   ",head[i] );
236         }
237         printf ( "\n\n== End Of Header dump ==\n" );
238         return ret;
239 }
240 
241 
242 void print_copyright()
243 {
244         printf ( "Part of bcm-utils package ver. " UTIL_VERSION " \n" );
245         printf ( "Copyright (C) 2009  Andrew 'Necromant' Andrianov\n"
246                  "This is free software, and you are welcome to redistribute it\n"
247                  "under certain conditions. See COPYING for details\n" );
248 }
249 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt