Setting up repository
[linux-libre-firmware.git] / ath9k_htc / sboot / magpie_1_1 / sboot / cmnos / rompatch / src / cmnos_rompatch.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted (subject to the limitations in the
7  * disclaimer below) provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *  * Neither the name of Qualcomm Atheros nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22  * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 /*************************************************************************/
36 /*  Copyright (c) 2008 Atheros Communications, Inc., All Rights Reserved */
37 /*                                                                       */
38 /*  Module Name : cmnos_rompatch.c                                       */
39 /*                                                                       */
40 /*  Abstract                                                             */
41 /*      This file contains rom code patch mechanism, patch code is       */
42 /*      offline generated, and replace the indirect table function as we */
43 /*      need to patch.                                                                                               */
44 /*                                                                       */
45 /*  NOTES                                                                */
46 /*      None                                                             */
47 /*                                                                       */
48 /*************************************************************************/
49
50 #include "sys_cfg.h"
51
52 #include "athos_api.h"
53
54 #if SYSTEM_MODULE_ROM_PATCH
55
56
57 LOCAL BOOLEAN _patch_dump( struct rom_patch_st *patch);
58 LOCAL BOOLEAN _read_rom_patch(struct rom_patch_st *patch);
59
60
61 // the patch install entry 
62 void (*patch_start)(void);
63
64 // the eep redirect addr
65 struct eep_redir_addr patch_addr =  {0x0, 0x0};
66
67
68 LOCAL
69 BOOLEAN _patch_dump( struct rom_patch_st *patch)
70 {
71 //    A_PRINTF("\tCRC: 0x%04x\n\r", patch->crc16);
72     A_PRINTF("\tsize: %d bytes\n\r", patch->len);
73     A_PRINTF("\tld_addr: 0x%08x\n\r", (uint32_t)patch->ld_addr);
74     A_PRINTF("\tfun_addr: 0x%08x\n\r", (uint32_t)patch->fun_addr);
75 }
76
77
78
79 LOCAL 
80 BOOLEAN _read_rom_patch(struct rom_patch_st *patch)
81 {
82     BOOLEAN retVal = FALSE;
83     uint8_t *addr;
84     uint16_t i;
85     uint8_t *buf = ((uint8_t*)(patch)+(sizeof(struct rom_patch_st)-4));  //assign the patch code buffer, last 4 bytes is the data
86
87     /*! assign the load address of the patch
88      * 
89      * - convert the address to dport address 0x4exxxx or 0x5xxxxx
90      */
91     //addr = (uint32_t *)((patch->ld_addr&(~0xc00000))|(0x400000));   
92     addr = (uint8_t *)(patch->ld_addr);
93     if( (uint32_t)addr < SYS_D_RAM_REGION_0_BASE || (uint32_t)addr >= (SYS_D_RAM_REGION_0_BASE + SYS_RAM_SZIE) )
94     {
95         A_PRINTF("!address should be dport in ram's address, 0x%08x\n\r", (uint32_t)addr);
96         goto ERR_DONE;
97     }
98     
99     _patch_dump(patch);
100    
101     A_PRINTF("copy %d bytes from 0x%08x to 0x%08x", patch->len, (uint32_t)buf, (uint32_t)addr);
102     for(i=0; i<patch->len; i+=4) // word access
103     {    
104         addr[i+3] = buf[i];
105         addr[i+2] = buf[i+1];
106         addr[i+1] = buf[i+2];
107         addr[i] = buf[i+3];
108     }
109
110     retVal =  TRUE;
111 ERR_DONE:
112     return retVal;
113
114 }
115
116
117 /*!
118  * decode and parse the rompatch code
119  *
120  * addr: the buffer in ram stored the downloaded buffer
121  */
122 LOCAL
123 BOOLEAN cmnos_romp_decode(uint32_t addr)
124 {
125     int i;
126     BOOLEAN retVal = FALSE;
127     struct rom_patch_st *patch;
128     uint8_t *func_addr;
129
130     A_PRINTF("[%s+]\n\r", __FUNCTION__ );
131     {
132         /* 
133          * check the integrity of the buffer
134          */
135         uint32_t *mData = (uint32_t *)addr;
136         uint32_t CheckSum = 0;
137
138         // size at here is a half-word based, divide by 2 set it to a word 
139         for(i=0; i<(patch_addr.size/2); i++, mData++)
140             CheckSum = CheckSum ^ *mData;
141
142         A_PRINTF("CheckSum: 0x%08x\n\r", CheckSum);
143
144         if( CheckSum != 0 )
145             goto ERR_DONE;
146
147         /*********************************************/
148         
149         patch = (struct rom_patch_st *)addr;
150         
151         func_addr = (uint8_t *)patch->fun_addr;
152         
153         if( _read_rom_patch(patch) )
154         {
155             //A_PRINTF("\n\r patch to 0x%08x, func at 0x%08x\n\r", (uint32_t)patch->ld_addr, (uint32_t)func_addr);
156
157             // the patch function entry, call install later
158             patch_start = (void *)func_addr;
159
160             // install the patch here
161             //patch_start();
162         }
163         else
164         {
165             A_PRINTF("patch decode fail!\n\r");
166             goto ERR_DONE;
167         }
168     }
169
170     retVal = TRUE;
171
172 ERR_DONE:
173     A_PRINTF("[%s-]\n\r", __FUNCTION__ );
174     
175     return retVal;
176         // 
177         //  if crc checking is ok, move code the where it belong according to it's ld_addr
178         // 
179     
180 }
181
182
183 /*!
184  * install
185  */
186 LOCAL BOOLEAN cmnos_romp_install(void)
187 {
188         /* TBD: to be removed! */
189
190     /*! call the patch function, 
191      * 
192      * - left the patch install did by the patch code,  
193      *   so that we sould build the patch code with entry function is the install process
194      *   e.g void install_patch(void), which update the function table
195      */
196
197     //A_PRINTF("[%s+]\n\r", __FUNCTION__);
198     patch_start();
199     //A_PRINTF("[%s-]\n\r", __FUNCTION__);
200 }
201
202 /*!
203  * download
204  *
205  *  offset: the offset of the eeprom redirect header(offset, size)
206  *
207  */
208 LOCAL BOOLEAN cmnos_romp_download(uint16_t offset)
209 {
210     BOOLEAN retVal = FALSE;
211     uint16_t buf[2];
212
213     uint16_t eep_start_ofst = EEPROM_START_OFFSET;
214     uint16_t eep_end_ofst = EEPROM_END_OFFSET;
215
216     A_PRINTF("[%s+]\n\r", __FUNCTION__ );
217
218     /* TBD: to be removed! */
219     /* read the patch from EEPROM, if there is an EEPROM exist and patch code stored inside */
220
221     /* 
222      * 1. read the fixed offset address of 0xfc and find the exactly patch code is
223      * 2. read the patch code from eeprom and write to buffer ram
224      * ------------------- leave it to decode operation ------------------
225      * 3. and check the integrity of it, if the integrity is ok, goto 4
226      * 4. decode the patch pack and decode each patch code and write them to the RAM 
227      * 
228      */
229
230     /*
231      * read the eep redirect(offset, size) from the offset
232      */
233      if( RET_SUCCESS != A_EEP_READ(offset, sizeof(struct eep_redir_addr)/sizeof(uint16_t), buf) )
234         goto ERR_DONE;
235
236     A_PRINTF("patch.offset: 0x%04x, patch.size : 0x%04x\n\r", buf[0], buf[1]);
237
238     patch_addr.offset = buf[0];
239     patch_addr.size = buf[1];
240     
241     // ATHR : 0x41544852, ((uint32_t)patch_addr == 0x41544852) || 
242     // size == 0, offset > 0x3fff or offset < 0x2000, eeprom offset is between 0x2000~0x3fff
243     if( (patch_addr.size == 0x0) ||(patch_addr.offset < eep_start_ofst )   \
244          || (patch_addr.offset > eep_end_ofst) || ((patch_addr.offset+patch_addr.size) > eep_end_ofst))
245         goto ERR_DONE;
246
247     // read the patch code to ROM_PATCH_BUF_ADDR: 0x51E000, 
248     A_EEP_READ(patch_addr.offset, patch_addr.size, (uint16_t *)ROM_PATCH_BUF_ADDR);
249
250     if( A_ROMP_DECODE(ROM_PATCH_BUF_ADDR) )
251     {
252         A_ROMP_INSTALL();
253     }
254     else
255         goto ERR_DONE;
256     
257     retVal = TRUE;
258 ERR_DONE:
259     A_PRINTF("[%s-]\n\r", __FUNCTION__ );
260     return retVal;
261
262 }
263
264 /*!
265  * init
266  */
267 LOCAL void cmnos_romp_init(void)
268 {
269         /* TBD: to be removed! */
270     //A_PRINTF("CMNOS_ROMP_INIT!\n\r");
271 }
272
273 void
274 cmnos_romp_module_install(struct romp_api *tbl)
275 {
276     tbl->_romp_init         = cmnos_romp_init;
277     tbl->_romp_download     = cmnos_romp_download;
278     tbl->_romp_install      = cmnos_romp_install;
279     tbl->_romp_decode       = cmnos_romp_decode;
280
281 }
282
283 #endif