root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/fwupgrade.c

Revision 12368, 4.0 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 /*
2 firmware upgrade code for DD-WRT webflash images
3 */
4
5 #include <redboot.h>
6 #include <cyg/io/flash.h>
7 #include <fis.h>
8 #include <flash_config.h>
9 #include "fwupgrade.h"
10
11 /* some variables from flash.c */
12 extern void *flash_start, *flash_end;
13 extern int flash_block_size, flash_num_blocks;
14 #ifdef CYGOPT_REDBOOT_FIS
15 extern void *fis_work_block;
16 extern void *fis_addr;
17 extern int fisdir_size;         // Size of FIS directory.
18 #endif
19 //extern void _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat);
20 extern void fis_update_directory(void);
21
22 //#define TRACE diag_printf("DBG: %s:%d\n", __FUNCTION__, __LINE__)
23
24 #define TRACE
25
26 #define TRX_MAGIC       0x30524448      /* "HDR0" */
27 #define TRX_VERSION     1
28 #define TRX_MAX_LEN     0x8A0000
29 #define TRX_NO_HEADER   1       /* Do not write TRX header */
30
31 //#if __BYTE_ORDER == __BIG_ENDIAN
32 unsigned int bswap_32(unsigned int *values)
33 {
34         unsigned char *p = (unsigned char *)values;
35         unsigned char a;
36         a = p[3];
37         p[3] = p[0];
38         p[0] = a;
39         a = p[2];
40         p[2] = p[1];
41         p[1] = a;
42         return *values;
43 }
44
45 #define STORE32_LE(X)           bswap_32(X)
46
47 //#elif __BYTE_ORDER == __LITTLE_ENDIAN
48 //#define STORE32_LE(X)         (X)
49 //#else
50 //#error unkown endianness!
51 //#endif
52
53 struct trx_header {
54         unsigned int magic;     /* "HDR0" */
55         unsigned int len;       /* Length of file including header */
56         unsigned int crc32;     /* 32-bit CRC from flag_version to end of file */
57         unsigned int flag_version;      /* 0:15 flags, 16:31 version */
58         unsigned int offsets[3];        /* Offsets of partitions from start of header */
59 };
60
61 extern void fis_init(int argc, char *argv[], int force);
62
63 int fw_check_image_ddwrt(unsigned char *addr, unsigned long maxlen,
64                          int do_flash)
65 {
66         struct trx_header *base = (struct trx_header *)addr;
67         struct trx_header trx;
68         memcpy(&trx, base, sizeof(trx));
69         trx.magic = STORE32_LE(&trx.magic);
70         trx.len = STORE32_LE(&trx.len);
71         trx.crc32 = STORE32_LE(&trx.crc32);
72         if (trx.magic != TRX_MAGIC || trx.len < sizeof(struct trx_header)) {
73                 diag_printf("DD-WRT_FW: Bad trx header\n");
74                 return -1;
75         }
76 //if (STORE32_LE(&trx.flag_version) & TRX_NO_HEADER)
77         trx.len -= sizeof(struct trx_header);
78
79         unsigned int crc;
80         crc =
81             cyg_crc32_accumulate(0xffffffff, (unsigned char *)&trx.flag_version,
82                                  sizeof(struct trx_header) - 12);
83         crc =
84             cyg_crc32_accumulate(crc, addr + sizeof(struct trx_header),
85                                  trx.len);
86         if (crc == trx.crc32) {
87                 if (!do_flash)
88                         diag_printf("DD-WRT_FW: DD-WRT FW CRC Okay\n");
89         } else {
90                 diag_printf
91                     ("DD-WRT_FW: DD-WRT FW CRC Failed (Calculated=0x%08X,Real=0x%08X\n",
92                      crc, trx.crc32);
93                 return -1;
94         }
95         if (do_flash) {
96                 char *arg[] = { "fis", "init" };
97                 fis_init(2, arg, 1);
98                 void *err_addr;
99                 flash_read(fis_addr, fis_work_block, fisdir_size,
100                            (void **)&err_addr);
101                 struct fis_image_desc *img = NULL;
102                 int i, stat;
103                 img = fis_lookup("RedBoot", &i);
104                 if (i != 0) {
105                         diag_printf
106                             ("DD-WRT_FW: RedBoot partition is not the first partition\n");
107                         return -1;
108                 }
109                 unsigned int flash_addr = img->flash_base + img->size;
110                 diag_printf("DD-WRT_FW: flash base is 0x%08X\n", flash_addr);
111                 if ((stat =
112                      flash_erase((void *)flash_addr, trx.len,
113                                  (void **)&err_addr)) != 0) {
114                         diag_printf("DD-WRT_FW: Can't erase region at %p: %s\n",
115                                     err_addr, flash_errmsg(stat));
116                         return -1;
117                 }
118                 if ((stat =
119                      flash_program((void *)flash_addr,
120                                    (void *)(addr + sizeof(struct trx_header)),
121                                    trx.len, (void **)&err_addr)) != 0) {
122                         diag_printf
123                             ("DD-WRT_FW: Can't program region at %p: %s\n",
124                              err_addr, flash_errmsg(stat));
125                         return -1;
126                 }
127                 img = fis_lookup("linux", &i);
128                 if (!img) {
129                         img = (struct fis_image_desc *)fis_work_block;
130                         for (i = 0; i < fisdir_size / sizeof(*img); i++, img++) {
131                                 if (img->name[0] == (unsigned char)0xFF) {
132                                         break;
133                                 }
134                         }
135                         memset(img, 0, sizeof(*img));
136                         strcpy(img->name, "linux");
137                 }
138                 img->flash_base = flash_addr;
139                 img->mem_base = 0x80041000;
140                 img->entry_point = 0x80041000;  // Hope it's been set
141                 img->size = trx.len;
142                 img->data_length = trx.len;
143                 fis_update_directory();
144                 diag_printf("DD-WRT_FW: flashing done\n");
145         }
146         return 0;
147 }
Note: See TracBrowser for help on using the browser.