Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / cmnos / rompatch / src / cmnos_rompatch.c
1 /*************************************************************************/
2 /*  Copyright (c) 2008 Atheros Communications, Inc., All Rights Reserved */
3 /*                                                                       */
4 /*  Module Name : cmnos_rompatch.c                                       */
5 /*                                                                       */
6 /*  Abstract                                                             */
7 /*      This file contains rom code patch mechanism, patch code is       */
8 /*      offline generated, and replace the indirect table function as we */
9 /*      need to patch.                                                                                               */
10 /*                                                                       */
11 /*  NOTES                                                                */
12 /*      None                                                             */
13 /*                                                                       */
14 /*************************************************************************/
15
16 #include "sys_cfg.h"
17
18 #include "athos_api.h"
19
20 #if SYSTEM_MODULE_ROM_PATCH
21
22
23 LOCAL BOOLEAN _patch_dump( struct rom_patch_st *patch);
24 LOCAL BOOLEAN _read_rom_patch(struct rom_patch_st *patch);
25
26
27 // the patch install entry 
28 void (*patch_start)(void);
29
30 // the eep redirect addr
31 struct eep_redir_addr patch_addr =  {0x0, 0x0};
32
33
34 LOCAL
35 BOOLEAN _patch_dump( struct rom_patch_st *patch)
36 {
37 //    A_PRINTF("\tCRC: 0x%04x\n\r", patch->crc16);
38     A_PRINTF("\tsize: %d bytes\n\r", patch->len);
39     A_PRINTF("\tld_addr: 0x%08x\n\r", (uint32_t)patch->ld_addr);
40     A_PRINTF("\tfun_addr: 0x%08x\n\r", (uint32_t)patch->fun_addr);
41 }
42
43
44
45 LOCAL 
46 BOOLEAN _read_rom_patch(struct rom_patch_st *patch)
47 {
48     BOOLEAN retVal = FALSE;
49     uint8_t *addr;
50     uint16_t i;
51     uint8_t *buf = ((uint8_t*)(patch)+(sizeof(struct rom_patch_st)-4));  //assign the patch code buffer, last 4 bytes is the data
52
53     /*! assign the load address of the patch
54      * 
55      * - convert the address to dport address 0x4exxxx or 0x5xxxxx
56      */
57     //addr = (uint32_t *)((patch->ld_addr&(~0xc00000))|(0x400000));   
58     addr = (uint8_t *)(patch->ld_addr);
59     if( (uint32_t)addr < SYS_D_RAM_REGION_0_BASE || (uint32_t)addr >= (SYS_D_RAM_REGION_0_BASE + SYS_RAM_SZIE) )
60     {
61         A_PRINTF("!address should be dport in ram's address, 0x%08x\n\r", (uint32_t)addr);
62         goto ERR_DONE;
63     }
64     
65     _patch_dump(patch);
66    
67     A_PRINTF("copy %d bytes from 0x%08x to 0x%08x", patch->len, (uint32_t)buf, (uint32_t)addr);
68     for(i=0; i<patch->len; i+=4) // word access
69     {    
70         addr[i+3] = buf[i];
71         addr[i+2] = buf[i+1];
72         addr[i+1] = buf[i+2];
73         addr[i] = buf[i+3];
74     }
75
76     retVal =  TRUE;
77 ERR_DONE:
78     return retVal;
79
80 }
81
82
83 /*!
84  * decode and parse the rompatch code
85  *
86  * addr: the buffer in ram stored the downloaded buffer
87  */
88 LOCAL
89 BOOLEAN cmnos_romp_decode(uint32_t addr)
90 {
91     int i;
92     BOOLEAN retVal = FALSE;
93     struct rom_patch_st *patch;
94     uint8_t *func_addr;
95
96     A_PRINTF("[%s+]\n\r", __FUNCTION__ );
97     {
98         /* 
99          * check the integrity of the buffer
100          */
101         uint32_t *mData = (uint32_t *)addr;
102         uint32_t CheckSum = 0;
103
104         // size at here is a half-word based, divide by 2 set it to a word 
105         for(i=0; i<(patch_addr.size/2); i++, mData++)
106             CheckSum = CheckSum ^ *mData;
107
108         A_PRINTF("CheckSum: 0x%08x\n\r", CheckSum);
109
110         if( CheckSum != 0 )
111             goto ERR_DONE;
112
113         /*********************************************/
114         
115         patch = (struct rom_patch_st *)addr;
116         
117         func_addr = (uint8_t *)patch->fun_addr;
118         
119         if( _read_rom_patch(patch) )
120         {
121             //A_PRINTF("\n\r patch to 0x%08x, func at 0x%08x\n\r", (uint32_t)patch->ld_addr, (uint32_t)func_addr);
122
123             // the patch function entry, call install later
124             patch_start = (void *)func_addr;
125
126             // install the patch here
127             //patch_start();
128         }
129         else
130         {
131             A_PRINTF("patch decode fail!\n\r");
132             goto ERR_DONE;
133         }
134     }
135
136     retVal = TRUE;
137
138 ERR_DONE:
139     A_PRINTF("[%s-]\n\r", __FUNCTION__ );
140     
141     return retVal;
142         // 
143         //  if crc checking is ok, move code the where it belong according to it's ld_addr
144         // 
145     
146 }
147
148
149 /*!
150  * install
151  */
152 LOCAL BOOLEAN cmnos_romp_install(void)
153 {
154         /* TBD: to be removed! */
155
156     /*! call the patch function, 
157      * 
158      * - left the patch install did by the patch code,  
159      *   so that we sould build the patch code with entry function is the install process
160      *   e.g void install_patch(void), which update the function table
161      */
162
163     //A_PRINTF("[%s+]\n\r", __FUNCTION__);
164     patch_start();
165     //A_PRINTF("[%s-]\n\r", __FUNCTION__);
166 }
167
168 /*!
169  * download
170  *
171  *  offset: the offset of the eeprom redirect header(offset, size)
172  *
173  */
174 LOCAL BOOLEAN cmnos_romp_download(uint16_t offset)
175 {
176     BOOLEAN retVal = FALSE;
177     uint16_t buf[2];
178
179     uint16_t eep_start_ofst = EEPROM_START_OFFSET;
180     uint16_t eep_end_ofst = EEPROM_END_OFFSET;
181
182     A_PRINTF("[%s+]\n\r", __FUNCTION__ );
183
184     /* TBD: to be removed! */
185     /* read the patch from EEPROM, if there is an EEPROM exist and patch code stored inside */
186
187     /* 
188      * 1. read the fixed offset address of 0xfc and find the exactly patch code is
189      * 2. read the patch code from eeprom and write to buffer ram
190      * ------------------- leave it to decode operation ------------------
191      * 3. and check the integrity of it, if the integrity is ok, goto 4
192      * 4. decode the patch pack and decode each patch code and write them to the RAM 
193      * 
194      */
195
196     /*
197      * read the eep redirect(offset, size) from the offset
198      */
199      if( RET_SUCCESS != A_EEP_READ(offset, sizeof(struct eep_redir_addr)/sizeof(uint16_t), buf) )
200         goto ERR_DONE;
201
202     A_PRINTF("patch.offset: 0x%04x, patch.size : 0x%04x\n\r", buf[0], buf[1]);
203
204     patch_addr.offset = buf[0];
205     patch_addr.size = buf[1];
206     
207     // ATHR : 0x41544852, ((uint32_t)patch_addr == 0x41544852) || 
208     // size == 0, offset > 0x3fff or offset < 0x2000, eeprom offset is between 0x2000~0x3fff
209     if( (patch_addr.size == 0x0) ||(patch_addr.offset < eep_start_ofst )   \
210          || (patch_addr.offset > eep_end_ofst) || ((patch_addr.offset+patch_addr.size) > eep_end_ofst))
211         goto ERR_DONE;
212
213     // read the patch code to ROM_PATCH_BUF_ADDR: 0x51E000, 
214     A_EEP_READ(patch_addr.offset, patch_addr.size, (uint16_t *)ROM_PATCH_BUF_ADDR);
215
216     if( A_ROMP_DECODE(ROM_PATCH_BUF_ADDR) )
217     {
218         A_ROMP_INSTALL();
219     }
220     else
221         goto ERR_DONE;
222     
223     retVal = TRUE;
224 ERR_DONE:
225     A_PRINTF("[%s-]\n\r", __FUNCTION__ );
226     return retVal;
227
228 }
229
230 /*!
231  * init
232  */
233 LOCAL void cmnos_romp_init(void)
234 {
235         /* TBD: to be removed! */
236     //A_PRINTF("CMNOS_ROMP_INIT!\n\r");
237 }
238
239 void
240 cmnos_romp_module_install(struct romp_api *tbl)
241 {
242     tbl->_romp_init         = cmnos_romp_init;
243     tbl->_romp_download     = cmnos_romp_download;
244     tbl->_romp_install      = cmnos_romp_install;
245     tbl->_romp_decode       = cmnos_romp_decode;
246
247 }
248
249 #endif