source: svn/trunk/newcon3bcm2_21bu/dta/src/app/image_write.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 11.6 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2008, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: $
11 * $brcm_Revision: $
12 * $brcm_Date: $
13 *
14 * Module Description: write image to flash.
15 *
16 * Revision History:
17 *
18 * $brcm_Log: $
19 *
20 *
21 ***************************************************************************/
22
23#include "bstd.h"
24#include "bdbg.h"
25
26#include "image_recv.h"
27#include "ramheader.h"
28#include "bfds.h"
29#include "gist.h"
30#include "bchp_sun_top_ctrl.h"
31
32BDBG_MODULE(image_write);
33
34bresult image_flash_install(uint32_t base, uint32_t offset, uint8_t * data, uint32_t size);
35bresult image_flash_install_fupdate(uint32_t base, uint32_t offset, uint8_t * data, uint32_t size);
36
37#if (CONFIG_ENABLE_SCM == 1)
38static int auth_image_authenticate(uint8_t *data);
39#endif
40 
41struct image_wstate_t {
42        bool berased;
43        int wpct;
44} ;
45static struct image_wstate_t wstate = {0,0};
46
47#define IMAGE1_SELECTOR_MASK    0x100
48#define SWAP_IMAGE(x,y) do { void *tmp = x; x=y;y=tmp; } while (0)
49
50bresult image_write(struct image_t * image)
51{
52    boot_header_t * ram0;   
53    boot_header_t * ram1;
54    uint32_t ram_offset;
55    unsigned int order0, order1, boot_order, reverse;
56#if (CONFIG_ENABLE_SCM==1)
57    int res;
58#endif
59               
60    wstate.berased = false;
61    wstate.wpct = 100;
62#if (CONFIG_ENABLE_SCM == 1)
63    /* authenticate receive image */
64    res = auth_image_authenticate(image->data);
65    if (res != 0) {
66        BDBG_WRN(("Image signature is not correct.. discard downloaded image"));
67        return berr_external_error;
68        }
69#endif
70
71    /* find running image */
72    ram0 = (boot_header_t *)FLASH_APP0_START;
73    ram1 = (boot_header_t *)FLASH_APP1_START;
74    /* figure out which image to replace */
75    order0 = order1 = boot_order = reverse = 0;
76    if ((image->size + sizeof(boot_header_t)) > FLASH_APP0_SIZE) {
77        /* couldn't store backup image, overwrite current image */
78        ram1 = ram0;
79    }   
80    else {
81        if (CHIP_ID == ram0->chip_id) order0 = ram0->boot_order;
82        if (CHIP_ID == ram1->chip_id) order1 = ram1->boot_order;
83        if (BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_UNCLEARED_SCRATCH) & IMAGE1_SELECTOR_MASK) {
84            if (order1 < order0) {
85                SWAP_IMAGE(ram0, ram1);
86                            reverse = 1;
87            }
88        }
89        else {
90            if (order1 > order0) {
91                SWAP_IMAGE(ram0, ram1);
92            }
93        }
94            if (CHIP_ID == ram0->chip_id)       {
95                    if (reverse) boot_order = ram0->boot_order-1;
96                    else boot_order = ram0->boot_order+1;
97            } else {
98                    ram1 = ram0;
99            }           
100    }
101
102    /* for now we will only write out first image */
103    ram_offset = (uint32_t)ram1 - (uint32_t)FLASH_BASE;
104    BDBG_WRN(("writing at 0x%x, size:%d", ram_offset, image->size));
105
106    /* fill boot_header space */
107    BKNI_Memset(image->header, 0xff, sizeof(boot_header_t));
108    ram0 = (boot_header_t *)image->header;
109    ram0->boot_order = boot_order;
110    ram0->chip_id = 0x7572;
111    return image_flash_install(FLASH_BASE, ram_offset, (uint8_t*)image->header, image->size+sizeof(boot_header_t));
112}
113
114bresult image_flash_install(uint32_t base, uint32_t offset, uint8_t * data, uint32_t size)
115{
116    bresult res;
117    int fds_err;
118    bfds_handle store;
119    bfds_properties fprop;
120    int sector_count;
121    int i;
122    void * page_data;
123    uint32_t remaining_size;
124    uint32_t block_size;
125    uint32_t curr_offset;
126
127    res = berr_external_error;
128    if (BFDS_OK != bfds_open(&store)){
129        goto ExitFunc;
130    }
131   
132    if (BFDS_OK != bfds_get_properties(store, &fprop)){
133        goto ExitFunc;
134    }
135
136    sector_count = size / fprop.flash_sector_size;
137    if(size % fprop.flash_sector_size){
138        sector_count += 1;
139    }
140    curr_offset = offset;
141    for(i = 0; i < sector_count; i++){
142        fds_err = bfds_sector_erase(store, curr_offset);
143        if(BFDS_OK != fds_err){
144            goto ExitFunc;
145        }
146        curr_offset += fprop.flash_sector_size;
147    }
148
149    wstate.berased = true;
150    i = 0;
151    bos_sleep(100); /* yield for osi update */ 
152
153    curr_offset = offset;
154    page_data = data;
155    remaining_size = size;
156    while(remaining_size > 0){
157        if(remaining_size > fprop.flash_page_size){
158            block_size = fprop.flash_page_size;
159        }else{
160            block_size = remaining_size;
161        }
162        fds_err = bfds_page_program(store, curr_offset, page_data, block_size);
163        if(BFDS_OK != fds_err){
164            goto ExitFunc;
165        }
166        remaining_size -= block_size;
167        page_data = (void*)((uint32_t)page_data + block_size);
168        curr_offset += block_size;
169
170        wstate.wpct = (remaining_size*100)/size;
171        if ((wstate.wpct % 4) == 0) {
172            if (wstate.wpct/4 != i) {
173                i = wstate.wpct/4;
174                bos_sleep(100);
175            }
176        }
177    }
178        return 0;
179ExitFunc:
180    return res;
181}
182
183bresult image_flash_install_fupdate(uint32_t base, uint32_t offset, uint8_t * data, uint32_t size)
184{
185    bresult res;
186    int fds_err;
187    bfds_handle store;
188    bfds_properties fprop;
189    int sector_count;
190    int i;
191    void * page_data;
192    uint32_t remaining_size;
193    uint32_t block_size;
194    uint32_t curr_offset;
195
196    res = berr_external_error;
197
198    if (BFDS_OK != bfds_open(&store)){
199        goto ExitFunc;
200    }
201   
202    if (BFDS_OK != bfds_get_properties(store, &fprop)){
203        goto ExitFunc;
204    }
205
206    sector_count = fprop.flash_total_size / fprop.flash_sector_size; 
207
208    curr_offset = offset;
209    for(i = 0; i < sector_count; i++){
210        fds_err = bfds_sector_erase(store, curr_offset);
211        if(BFDS_OK != fds_err){
212            goto ExitFunc;
213        }
214        curr_offset += fprop.flash_sector_size;
215    }
216
217    wstate.berased = true;
218    i = 0;
219    bos_sleep(100); /* yield for osi update */ 
220
221    curr_offset = offset;
222    page_data = data;
223    remaining_size = size;
224    while(remaining_size > 0){
225        if(remaining_size > fprop.flash_page_size){
226            block_size = fprop.flash_page_size;
227        }else{
228            block_size = remaining_size;
229        }
230        fds_err = bfds_page_program(store, curr_offset, page_data, block_size);
231        if(BFDS_OK != fds_err){
232            goto ExitFunc;
233        }
234        remaining_size -= block_size;
235        page_data = (void*)((uint32_t)page_data + block_size);
236        curr_offset += block_size;
237
238        wstate.wpct = (remaining_size*100)/size;
239        if ((wstate.wpct % 4) == 0) {
240            if (wstate.wpct/4 != i) {
241                i = wstate.wpct/4;
242                bos_sleep(100);
243            }
244        }
245    }
246        return 0;
247ExitFunc:
248    return res;
249}
250
251void image_get_wstate(bool *berased, int *wpct)
252{
253        *berased = wstate.berased;
254        *wpct = wstate.wpct;
255}
256
257#if (CONFIG_ENABLE_SCM == 1)
258#include "signature.c"
259const unsigned int broadcom_test_key[0x100/4] =
260{
261    0xbb4b3dac,0xaad0a0f7,0x69efdb63,0x0f0cf45d,
262    0xa8bee481,0xdae2ced3,0xb2a35773,0xb859cb6d,
263    0xc42a5f7d,0x0b02b5a6,0x40e81bde,0x592afa2c,
264    0xc6b0f440,0xc27adc14,0xa499709b,0xc6c06c05,
265    0x7fc11902,0xbcc63a02,0x68f07420,0xa701267f,
266    0xee6db3b1,0x7d563cd6,0xf749d20a,0x38f546f8,
267    0x805bbc09,0xa184b617,0xd1d2f5d7,0xe20de8be,
268    0x84b471a7,0x8d57e5f5,0x7d3cec98,0x290f3ad1,
269    0x1e6dbfa9,0x5e28a674,0xf02d0afc,0xe8f90d41,
270    0x033c6fd2,0x2b02f77d,0xcfe718af,0x0741699b,
271    0x4c933cba,0x71135d5e,0x3016bb7a,0x449efe72,
272    0xbfdd6f79,0x5849551a,0xa6e38ac3,0x9d74c7aa,
273    0xc6a3eb11,0xa20d3d63,0x55d74702,0xdaa1bd7c,
274    0x8af2ab33,0x694ba3bf,0xbd39dd1e,0x4b371322,
275    0x4593bf32,0x037837ba,0x1c854644,0xd6815619,
276    0x0e9720de,0xea891def,0x4bffc70f,0x1c1b92a7,
277};
278
279/* production SCM modulus */
280const unsigned int scm_key[0x100/4] = 
281{
282    0xbb4b3dac,0xaad0a0f7,0x69efdb63,0x0f0cf45d,
283    0xa8bee481,0xdae2ced3,0xb2a35773,0xb859cb6d,
284    0xc42a5f7d,0x0b02b5a6,0x40e81bde,0x592afa2c,
285    0xc6b0f440,0xc27adc14,0xa499709b,0xc6c06c05,
286    0x7fc11902,0xbcc63a02,0x68f07420,0xa701267f,
287    0xee6db3b1,0x7d563cd6,0xf749d20a,0x38f546f8,
288    0x805bbc09,0xa184b617,0xd1d2f5d7,0xe20de8be,
289    0x84b471a7,0x8d57e5f5,0x7d3cec98,0x290f3ad1,
290    0x1e6dbfa9,0x5e28a674,0xf02d0afc,0xe8f90d41,
291    0x033c6fd2,0x2b02f77d,0xcfe718af,0x0741699b,
292    0x4c933cba,0x71135d5e,0x3016bb7a,0x449efe72,
293    0xbfdd6f79,0x5849551a,0xa6e38ac3,0x9d74c7aa,
294    0xc6a3eb11,0xa20d3d63,0x55d74702,0xdaa1bd7c,
295    0x8af2ab33,0x694ba3bf,0xbd39dd1e,0x4b371322,
296    0x4593bf32,0x037837ba,0x1c854644,0xd6815619,
297    0x0e9720de,0xea891def,0x4bffc70f,0x1c1b92a7,
298};
299
300static int auth_image_authenticate(uint8_t *data)
301{
302    application_info_header_t *ah;
303    unsigned long signed_size;
304    unsigned long signature_addr;
305    scm_info_header_t *sh;
306    int res;
307
308    res = 1;
309    ah = (application_info_header_t *)data;
310    if (ah->chip_id != 0x7572) {
311        BDBG_WRN(("Application header not found"));
312        goto ExitFunc;
313    }
314
315        /* TODO:: key should be read from storage.. */
316    signed_size = sizeof(application_info_header_t) + ah->image_size;
317    signature_addr = (unsigned long)ah + signed_size;
318    res = signature_check((unsigned long)ah, signed_size, signature_addr, (unsigned long)broadcom_test_key);
319    if (0 != res) {
320        BDBG_WRN(("Application signature check failed"));
321                res = 0;
322                /* currently we are attaching fake.sig for application. */
323                /*     
324                goto ExitFunc;
325                */
326    }
327    sh = (scm_info_header_t *)(signature_addr + 0x100);
328    if ((CHIP_ID != sh->chip_id) || (SCM_MAGIC != sh->scm_magic)) {
329        res = 1;
330        BDBG_WRN(("DSP loader header not found"));
331        goto ExitFunc;
332    }
333    signed_size = sizeof(scm_info_header_t) + sh->image_size;
334    signature_addr = (unsigned long)sh + signed_size;
335    res = signature_check((unsigned long)sh, signed_size, signature_addr, (unsigned long)scm_key);
336    if (0 != res) {
337        BDBG_WRN(("DSP loader signature check failed"));
338    }
339ExitFunc:
340    return res;
341}
342#endif
343
344/*
345 * return application info header structure if exists
346 *
347 * bank: 0 or 1 for BANK A/B
348 * bact: [return] will be true if it's active image
349 * return pointer application header. If not exists, will be NULL
350 */
351void *image_get_header(int bank, bool *bact)
352{
353        boot_header_t * ram0;
354        boot_header_t * ram1;
355        application_info_header_t *app_header = NULL;
356        unsigned int order0, order1, reverse = 0;
357        int active = -1;
358
359        ram0 = (boot_header_t *)FLASH_APP0_START;
360        ram1 = (boot_header_t *)FLASH_APP1_START;
361
362        *bact = false;
363        if (BREG_Read32(GetREG(), BCHP_SUN_TOP_CTRL_UNCLEARED_SCRATCH) & IMAGE1_SELECTOR_MASK) 
364                reverse = 1;
365
366        if (CHIP_ID == ram0->chip_id) {
367                order0 = ram0->boot_order;
368                if (CHIP_ID == ram1->chip_id) {
369                        order1 = ram1->boot_order;
370
371                        if (reverse && (order1 < order0)) active = 1;
372                        else if (!reverse && (order1 > order0)) active = 1;
373                        else active = 0;
374                        if (bank == 1) 
375                                app_header = (application_info_header_t *)(FLASH_APP1_START + sizeof(boot_header_t));
376                }
377                else {
378                        active = 0;
379                }
380                if (bank == 0) 
381                        app_header = (application_info_header_t *)(FLASH_APP0_START + sizeof(boot_header_t));
382        }
383        else if (CHIP_ID == ram1->chip_id) {
384                active = 1;
385                if (bank == 1) 
386                        app_header = (application_info_header_t *)(FLASH_APP1_START + sizeof(boot_header_t));
387        }
388
389        if (bank == active) 
390                *bact = true;
391
392        /* verify application header is correct or not */
393        if (app_header && ((app_header->chip_id != CHIP_ID) || (app_header->dta_magic != DTA_MAGIC))) {
394                /* invalid application header */
395                app_header = NULL;
396        }
397
398        return (void *)app_header;
399}
400
401/* Please do not remove! */
402/* Local Variables: */
403/* mode: C */
404/* indent-tabs-mode: nil */
405/* End: */
Note: See TracBrowser for help on using the repository browser.