source: svn/trunk/newcon3bcm2_21bu/magnum/commonutils/afl/bafl.c

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

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 18.0 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2009-2011, 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: bafl.c $
11 * $brcm_Revision: Hydra_Software_Devel/6 $
12 * $brcm_Date: 8/8/11 3:16p $
13 *
14 * [File Description:]
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/commonutils/afl/bafl.c $
19 *
20 * Hydra_Software_Devel/6   8/8/11 3:16p rayshap
21 * SW7346-406: Add coverity comment to suppress erroneous errors
22 *
23 * Hydra_Software_Devel/5   2/3/11 6:07p davidp
24 * SW7346-18: Fix un-aligned src address case.
25 *
26 * Hydra_Software_Devel/4   1/19/11 2:04p davidp
27 * SW7344-5: Add support for BE systems.
28 *
29 * Hydra_Software_Devel/3   10/19/10 5:00p davidp
30 * SW7425-16: Change BAFL_SectionInfo to specify start address, not
31 * offset.
32 *
33 * Hydra_Software_Devel/2   10/7/10 3:54p davidp
34 * SW7425-1: Change datatype of load info StartAddress to void *.
35 *
36 * Hydra_Software_Devel/1   8/27/10 4:33p davidp
37 * SW7425-1: Merge from branch.
38 *
39 * Hydra_Software_Devel/SW7425-1/1   8/18/10 4:54p davidp
40 * SW7425-1: Add initial version of Broadcom ARC Firmware Loader.
41 *
42 ***************************************************************************/
43
44#include "bstd.h"
45#include "bdbg.h"
46#include "berr.h"
47#include "bimg.h"
48#include "bkni.h"
49
50#include "bafl.h"
51#include "bafl_elf.h"
52
53BDBG_MODULE(BAFL);
54
55/* Uncomment the following line to include more detailed debug messages */
56/* #define BAFL_DEBUG_DETAIL_MSGS 1  */
57
58#define BAFL_MAX_SHDR          128
59#define LSRAM 0x30000000
60
61#define BAFL_IMAGE_FW_BLOCK_SIZE 16384
62
63typedef struct
64{     
65      int32_t    swap_required;
66      BAFL_Elf32_Ehdr header;
67      BAFL_Elf32_Shdr section_header[BAFL_MAX_SHDR];
68} ElfInfo;
69
70typedef struct
71{
72      uint32_t uiCurImgBlock;
73      uint32_t uiCurImgBlockAddr;
74} BAFL_P_ImageInfo;
75
76/* Get a 32 bit value and swap it if necessary. */
77#define BAFL_P_Elf_Swap32(n)            \
78         n = ((n & 0xFF000000) >> 24) | \
79             ((n & 0x00FF0000) >>  8) | \
80             ((n & 0x0000FF00) <<  8) | \
81             ((n & 0x000000FF) << 24);
82
83/* Get a 16 bit value and swap it if necessary. */
84#define BAFL_P_Elf_Swap16(n)         \
85         n = ((n & 0xFF00) >> 8) |   \
86             ((n & 0x00FF) << 8);   
87
88static BERR_Code BAFL_P_CopyFWImageToMem( uint8_t* pDestPtr,
89                                         uint32_t uiNumBytes,
90                                         uint32_t uiOffset,
91                                         BAFL_P_ImageInfo *pImageInfo,
92                                         BIMG_Method_Next ImageNextFunc,
93                                         void *pImage,
94                                         bool bByteSwap);
95
96BERR_Code BAFL_Load ( const BIMG_Interface *pImgInterface,
97                      void **pImageContext,
98                      uint32_t uiInstance,
99                      void *pStartAddress, /* Virtual Address */
100                      size_t uiSize,
101                      bool bDataOnly,
102                      BAFL_FirmwareLoadInfo *pstFWLoadInfo )
103{ 
104   ElfInfo *pElfInfo;
105   BAFL_P_ImageInfo stImageInfo;
106
107   BAFL_Elf32_Ehdr *pElfHdr;   /* ELF header */
108   BAFL_Elf32_Shdr *pSHdr;     /* Section table header */
109
110   uint32_t uiTransSize;
111
112   uint32_t uiSHdr;
113   uint32_t i;
114
115   uint32_t uiDestBase;
116
117   bool bFoundDataSection = false;
118
119   void *pImage;
120
121   BERR_Code rc = BERR_SUCCESS;
122
123   BDBG_ASSERT(pImgInterface);
124
125   BDBG_MSG(("Opening firmware image ID: %d", uiInstance));
126 
127   rc = pImgInterface->open(pImageContext,
128                            &pImage,
129                            uiInstance);
130
131   stImageInfo.uiCurImgBlock = 0xffff;
132   stImageInfo.uiCurImgBlockAddr = 0;
133
134   pElfInfo = (ElfInfo *) BKNI_Malloc(sizeof(ElfInfo));
135
136   if (!pElfInfo)
137   {
138      BDBG_ERR(("unable to allocate Elf Info structure"));
139      return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
140   }
141
142   BKNI_Memset((void *)pElfInfo, 0, sizeof(ElfInfo));
143
144   rc = BAFL_P_CopyFWImageToMem((uint8_t *)&(pElfInfo->header), /* pDestPtr */
145                                sizeof(BAFL_Elf32_Ehdr),        /* uiNumBytes */
146                                0,                              /* uiOffset */
147                                &stImageInfo,                   
148                                pImgInterface->next,           
149                                pImage, 
150                                false); /* No byte swap */
151
152   if (rc != BERR_SUCCESS)
153   {
154      BKNI_Free(pElfInfo);
155      return rc;
156   }
157
158#if (BSTD_CPU_ENDIAN == BSTD_ENDIAN_LITTLE)
159   pElfInfo->swap_required = (pElfInfo->header.e_ident[BAFL_EI_DATA] == BAFL_ELFDATA2LSB) ? 0 : 1;
160#else
161   pElfInfo->swap_required = (pElfInfo->header.e_ident[BAFL_EI_DATA] == BAFL_ELFDATA2LSB) ? 1 : 0;
162#endif
163
164   BDBG_MSG(("Header %s endianess of system - byteswapping %s occur (data=%d)",
165             pElfInfo->swap_required?"does not match":"matches", 
166             pElfInfo->swap_required?"will":"will not", 
167             pElfInfo->header.e_ident[BAFL_EI_DATA]));
168
169   if (pElfInfo->swap_required)
170   {
171      BAFL_P_Elf_Swap16(pElfInfo->header.e_type);
172      BAFL_P_Elf_Swap16(pElfInfo->header.e_machine);
173      BAFL_P_Elf_Swap32(pElfInfo->header.e_version);
174      BAFL_P_Elf_Swap32(pElfInfo->header.e_entry);
175      BAFL_P_Elf_Swap32(pElfInfo->header.e_phoff);
176      BAFL_P_Elf_Swap32(pElfInfo->header.e_shoff);
177      BAFL_P_Elf_Swap32(pElfInfo->header.e_flags);
178      BAFL_P_Elf_Swap16(pElfInfo->header.e_ehsize);
179      BAFL_P_Elf_Swap16(pElfInfo->header.e_phentsize);
180      BAFL_P_Elf_Swap16(pElfInfo->header.e_phnum);
181      BAFL_P_Elf_Swap16(pElfInfo->header.e_shentsize);
182      BAFL_P_Elf_Swap16(pElfInfo->header.e_shnum);
183      BAFL_P_Elf_Swap16(pElfInfo->header.e_shstrndx);
184   }
185
186   pElfHdr = (BAFL_Elf32_Ehdr *) &(pElfInfo->header);
187
188#if BAFL_DEBUG_DETAIL_MSGS
189   BDBG_MSG(("Elf32_Ehdr"));
190   BDBG_MSG(("\te_type: %0x", (uint32_t) pElfHdr->e_type));
191   BDBG_MSG(("\te_machine: %d", (uint32_t) pElfHdr->e_machine));
192   BDBG_MSG(("\te_version: %d", (uint32_t) pElfHdr->e_version));
193   BDBG_MSG(("\te_entry: %0x", (uint32_t) pElfHdr->e_entry));
194   BDBG_MSG(("\te_phoff: 0x%0x", (uint32_t) pElfHdr->e_phoff));
195   BDBG_MSG(("\te_shoff: 0x%0x", (uint32_t) pElfHdr->e_shoff));
196   BDBG_MSG(("\te_flags: 0x%0x", (uint32_t) pElfHdr->e_flags));
197   BDBG_MSG(("\te_ehsize: %d", (uint32_t) pElfHdr->e_ehsize));
198   BDBG_MSG(("\te_phentsize: %d", (uint32_t) pElfHdr->e_phentsize));
199   BDBG_MSG(("\te_phnum: %d", (uint32_t) pElfHdr->e_phnum));
200   BDBG_MSG(("\te_shentsize: %d", (uint32_t) pElfHdr->e_shentsize));
201   BDBG_MSG(("\te_shnum: %d", (uint32_t) pElfHdr->e_shnum));
202   BDBG_MSG(("\te_shstrndx: %d", (uint32_t) pElfHdr->e_shstrndx));
203#endif
204
205   /* Read in ELF Section Table */
206
207   uiSHdr = pElfHdr->e_shoff; /* Section table offset */
208   pSHdr    = &pElfInfo->section_header[0];
209
210   uiTransSize = sizeof(BAFL_Elf32_Shdr) * pElfInfo->header.e_shnum;
211
212   rc = BAFL_P_CopyFWImageToMem((uint8_t *)pSHdr,     /* pDestPtr */
213                                uiTransSize,          /* uiNumBytes */
214                                uiSHdr,               /* uiOffset */
215                                &stImageInfo,         
216                                pImgInterface->next, 
217                                pImage,
218                                false); /* No byte swap */
219   if (rc != BERR_SUCCESS)
220   {
221      BKNI_Free(pElfInfo);
222      return rc;
223   }
224
225   for (i = 0; i < pElfInfo->header.e_shnum; i++)
226   {
227      if (pElfInfo->swap_required)
228      {
229         BAFL_P_Elf_Swap32(pSHdr->sh_name);
230         BAFL_P_Elf_Swap32(pSHdr->sh_type);
231         BAFL_P_Elf_Swap32(pSHdr->sh_flags);
232         BAFL_P_Elf_Swap32(pSHdr->sh_addr);
233         BAFL_P_Elf_Swap32(pSHdr->sh_offset);
234         BAFL_P_Elf_Swap32(pSHdr->sh_size);
235         BAFL_P_Elf_Swap32(pSHdr->sh_link);
236         BAFL_P_Elf_Swap32(pSHdr->sh_info);
237         BAFL_P_Elf_Swap32(pSHdr->sh_addralign);
238         BAFL_P_Elf_Swap32(pSHdr->sh_entsize);
239      }
240
241#if BAFL_DEBUG_DETAIL_MSGS
242      {
243         BDBG_MSG((" "));
244         BDBG_MSG(("Sect hdr: %d", i));
245         BDBG_MSG(( "pSHdr->sh_name: %0x", (uint32_t) pSHdr->sh_name));
246         BDBG_MSG(( "pSHdr->sh_type: %0x", (uint32_t) pSHdr->sh_type));
247         BDBG_MSG(( "pSHdr->sh_flags: %0x", (uint32_t) pSHdr->sh_flags));
248         BDBG_MSG(( "pSHdr->sh_addr: %0x", (uint32_t) pSHdr->sh_addr));
249         BDBG_MSG(( "pSHdr->sh_offset: %0x", (uint32_t) pSHdr->sh_offset));
250         BDBG_MSG(( "pSHdr->sh_size: %0x", (uint32_t) pSHdr->sh_size));
251         BDBG_MSG(( "pSHdr->sh_link: %0x", (uint32_t) pSHdr->sh_link));
252         BDBG_MSG(( "pSHdr->sh_info: %0x", (uint32_t) pSHdr->sh_info));
253         BDBG_MSG(( "pSHdr->sh_addralign: %0x", (uint32_t) pSHdr->sh_addralign));
254         BDBG_MSG(( "pSHdr->sh_entsize: %0x", (uint32_t) pSHdr->sh_entsize));
255      }
256#endif
257      pSHdr++;
258   }
259
260/* Copy section data */
261
262   BDBG_MSG(("Number of sections: %d", pElfInfo->header.e_shnum));
263
264   for (i = 1; i < pElfInfo->header.e_shnum; i++)
265   {
266      if ( pElfInfo->section_header[i].sh_size == 0 )
267      {
268#if BAFL_DEBUG_DETAIL_MSGS
269         BDBG_MSG(("section size = 0... skipping"));
270#endif
271         continue;
272      }
273
274      if ((pElfInfo->section_header[i].sh_flags & BAFL_SHF_ALLOC) == 0)
275      {
276#if BAFL_DEBUG_DETAIL_MSGS
277         BDBG_MSG(("sh_flags & SHF_ALLOC... skipping"));
278#endif
279         continue;
280      }
281
282      if ( pElfInfo->section_header[i].sh_type != BAFL_SHT_PROGBITS )
283      {
284#if BAFL_DEBUG_DETAIL_MSGS
285         BDBG_MSG(("not a PROGBITS section... skipping"));
286#endif
287         continue;
288      }
289
290      if ( pElfInfo->section_header[i].sh_addr >= LSRAM )
291      {
292#if BAFL_DEBUG_DETAIL_MSGS
293         BDBG_MSG(("section addr >= 0x30000000... done"));
294#endif
295         break;
296      }
297
298      if ( !(pElfInfo->section_header[i].sh_flags & BAFL_SHF_EXECINSTR ) )
299      {
300         BDBG_MSG(("Load Data section"));
301         if (bFoundDataSection == false)
302         {
303            bFoundDataSection = true;
304
305            pstFWLoadInfo->stCode.pStartAddress = pStartAddress;
306            pstFWLoadInfo->stCode.uiSize = pElfInfo->section_header[i].sh_addr;
307
308            pstFWLoadInfo->stData.pStartAddress = (uint8_t*)pStartAddress + pElfInfo->section_header[i].sh_addr;
309            pstFWLoadInfo->stData.uiSize = uiSize - pElfInfo->section_header[i].sh_addr;
310         }
311      }
312      else if (bDataOnly)
313      {
314         BDBG_MSG(("Load data only... Skip executable section"));
315         continue;
316      }
317      else
318      {
319         BDBG_MSG(("Load executable section"));
320      }       
321
322      /* Calculate the base address of this section where the image is being copied to. */
323      uiDestBase = pElfInfo->section_header[i].sh_addr + (uint32_t)pStartAddress;
324
325#if BAFL_DEBUG_DETAIL_MSGS
326      BDBG_MSG(("Load Section %d", i));
327      BDBG_MSG(("\tFW Base Address: %0x", pStartAddress));
328      BDBG_MSG(("\tSection Base: %08x", uiDestBase));
329      BDBG_MSG(("\tDest Offset: %08x", pElfInfo->section_header[i].sh_addr));
330      BDBG_MSG(("\tImageSectoffset: %0x", pElfInfo->section_header[i].sh_offset));
331#endif
332     
333      if (pElfInfo->section_header[i].sh_size +  pElfInfo->section_header[i].sh_offset > uiSize)
334      {
335         BDBG_ERR(("FW memory size too small for image"));
336         return (BERR_INVALID_PARAMETER);
337      }
338
339      rc = BAFL_P_CopyFWImageToMem((uint8_t *)uiDestBase,                 /* pDestPtr */
340                                   pElfInfo->section_header[i].sh_size,   /* uiNumBytes */
341                                   pElfInfo->section_header[i].sh_offset, /* uiOffset */
342                                   &stImageInfo,                   
343                                   pImgInterface->next,           
344                                   pImage,
345                                   pElfInfo->swap_required);
346
347      if (rc != BERR_SUCCESS)
348      {
349         BKNI_Free(pElfInfo);
350         return rc;
351      }
352   }
353
354   pImgInterface->close(pImage);
355
356   BDBG_MSG(("LoadInfo Code Start Address: %08x, Size: %08x", 
357             pstFWLoadInfo->stCode.pStartAddress, pstFWLoadInfo->stCode.uiSize));
358
359   BDBG_MSG(("LoadInfo Data Start Address: %08x, Size: %08x", 
360             pstFWLoadInfo->stData.pStartAddress, pstFWLoadInfo->stData.uiSize));
361
362   BKNI_Free(pElfInfo);
363
364   return (BERR_SUCCESS);
365}
366
367static void BAFL_ByteSwapMemcpy(uint8_t *pDestPtr,
368                                uint8_t *pSrcPtr,
369                                uint32_t uiBytesToCopy)
370{
371   uint32_t word;
372   uint32_t *pTmp;
373   uint32_t uiBytePos;
374
375   /* Check to see if starting destination ptr on word boundary */
376   if ( ((uint32_t)pDestPtr & 0x00000003) != 0x00)
377   {
378      pTmp = (uint32_t*) ((uint32_t)pDestPtr & 0xfffffffc);
379
380      word = *pTmp;
381
382      uiBytePos = (uint32_t) pDestPtr - (uint32_t) pTmp;
383
384      switch (uiBytePos)
385      {
386         case 1:
387            word &= 0xffff00ff;
388            word |= ((*pSrcPtr & 0xff) <<  8);
389            pSrcPtr++;
390            /* coverity[unterminated_case] */
391         case 2:
392            word &= 0xff00ffff;
393            word |= ((*pSrcPtr & 0xff) <<  16);
394            pSrcPtr++;
395            /* coverity[unterminated_case] */
396         case 3:
397            word &= 0x00ffffff;
398            word |= ((*pSrcPtr & 0xff) <<  24);
399            pSrcPtr++;
400      }
401
402      *pTmp = word;
403
404      pDestPtr += (4 - uiBytePos);
405      uiBytesToCopy -= (4 - uiBytePos);
406   }
407     
408   /* Copy long word aligned word length data */
409   while (uiBytesToCopy > 3)
410   {
411      word = 0;
412
413      word = ((pSrcPtr[3] & 0xff) << 24) |
414             ((pSrcPtr[2] & 0xff) << 16) |
415             ((pSrcPtr[1] & 0xff) <<  8) |
416             ((pSrcPtr[0] & 0xff) <<  0);
417
418      *(uint32_t *)pDestPtr = word;
419
420      pSrcPtr += 4;
421      pDestPtr += 4;
422      uiBytesToCopy  -= 4;
423   }
424
425   /* Copy last non word data if exists */
426   if (uiBytesToCopy > 0)
427   {
428      word = 0;
429      switch (uiBytesToCopy)
430      {
431         case 3: word |= (pSrcPtr[2] & 0xff) << 16;
432         /* coverity[unterminated_case] */
433         case 2: word |= (pSrcPtr[1] & 0xff) <<  8;
434         /* coverity[unterminated_case] */
435         case 1: word |= (pSrcPtr[0] & 0xff) <<  0;
436            break;
437      }
438
439      *(uint32_t *)pDestPtr = word;
440   }
441}
442
443
444/*
445 * BAFL_P_CoptFWImageToMem
446 *
447 * This routine copies a number of bytes from the specified offset of the image to
448 * the destination address. This routine uses the bimg interface to access the appropriate
449 * block(s) of the image. The block that is currently open is saved from call to call.
450 */
451
452BERR_Code BAFL_P_CopyFWImageToMem(uint8_t* pDestPtr,
453                                  uint32_t uiNumBytes,
454                                  uint32_t uiOffset,
455                                  BAFL_P_ImageInfo *pImageInfo,
456                                  BIMG_Method_Next ImageNextFunc,
457                                  void *pImage,
458                                  bool bByteSwap)
459{
460   BERR_Code rc; 
461   uint32_t uiStartBlock, uiEndBlock, i;
462   const void *pImageDataBlock;
463   uint32_t uiCopyOffset = 0;
464   uint32_t uiBytesToCopy;
465   uint32_t uiBytesLeft = uiNumBytes;
466
467   BDBG_ENTER(BAFL_P_CopyFWImageToMem);       
468
469   if (uiNumBytes == 0){
470
471      BDBG_MSG(("Zero size image, FW image NOT loaded."));
472
473      return BERR_TRACE(BERR_SUCCESS);
474   }
475
476#if BAFL_DEBUG_DETAIL_MSGS
477   BDBG_MSG(("CopyFWImageToMem: size is %x at address %x", uiNumBytes, pDestPtr));
478#endif
479
480   /* Read the firmware image in blocks of BAFL_IMAGE_FW_BLOCK_SIZE.
481    * This function will copy any byte offset and size from the
482    * image to memory. In order to do this, this routine needs to
483    * handle the various cases:
484    *
485    * - Start Condition
486    *  o uiOffset is 0 or a multiple of a block (We can start
487    *    copying the block from the beginning)
488    *  o uiOffset is not a multiple of a block (We need to start
489    *    copying from an offset into the first block)
490    * - Middle Condition
491    *  o If the bytes left to copy is greater than the block size,
492    *    then we can just copy the entire block
493    * - End Condition
494    *  o (uiOffset + uiNumBytes) ends on a block boundary (We can
495    *    copy the last block until the end)
496    *  o (uiOffset + uiNumBytes) does NOT end on a block boundary
497    *    (We copy only a portion of the last block)
498    */
499
500   uiStartBlock = (uiOffset / BAFL_IMAGE_FW_BLOCK_SIZE) + 1;
501   uiEndBlock = ((uiOffset + uiNumBytes - 1) / BAFL_IMAGE_FW_BLOCK_SIZE) + 1;
502
503   if (uiOffset % BAFL_IMAGE_FW_BLOCK_SIZE) 
504   {
505      uiCopyOffset = (uiOffset % BAFL_IMAGE_FW_BLOCK_SIZE);
506   }
507   
508   for (i = uiStartBlock; i <= uiEndBlock; i++) 
509   {
510      if (i == pImageInfo->uiCurImgBlock)
511      {
512         pImageDataBlock = (void *)pImageInfo->uiCurImgBlockAddr;
513      }
514      else
515      {
516         /* Retrieve next block */
517         rc = ImageNextFunc(pImage,
518                            i, 
519                            &pImageDataBlock,
520                            BAFL_IMAGE_FW_BLOCK_SIZE);
521
522         if (rc != BERR_SUCCESS)
523         {
524            BDBG_ERR(("Error reading image block: %d", i));
525            return BERR_TRACE(rc);
526         }
527
528         pImageInfo->uiCurImgBlock = i;
529         pImageInfo->uiCurImgBlockAddr = (uint32_t)pImageDataBlock;
530      }
531       
532      /* Determine how many bytes of this block we need to
533       * copy */
534      if (uiBytesLeft > (BAFL_IMAGE_FW_BLOCK_SIZE - uiCopyOffset))
535      {
536         uiBytesToCopy = BAFL_IMAGE_FW_BLOCK_SIZE - uiCopyOffset;
537      }
538      else 
539      {
540         uiBytesToCopy = uiBytesLeft;
541      }
542
543#if BAFL_DEBUG_DETAIL_MSGS
544      BDBG_MSG(("pDestPtr: %08x Bytes: %d", pDestPtr, uiBytesToCopy));
545#endif
546 
547      if (bByteSwap == true)
548      {
549         BAFL_ByteSwapMemcpy(pDestPtr,
550                             (uint8_t*)pImageDataBlock + uiCopyOffset, 
551                             uiBytesToCopy);
552      }
553      else
554      {
555         /* Copy image block to FW memory region */
556         BKNI_Memcpy(pDestPtr, 
557                     (uint8_t*)pImageDataBlock + uiCopyOffset, 
558                     uiBytesToCopy);
559      }
560
561      pDestPtr += uiBytesToCopy;           
562      uiBytesLeft -= uiBytesToCopy;
563      uiCopyOffset = 0;
564   }
565
566   BDBG_LEAVE(BAFL_P_CopyFWImageToMem);
567
568   return BERR_TRACE(BERR_SUCCESS);
569}
Note: See TracBrowser for help on using the repository browser.