| 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 | |
|---|
| 53 | BDBG_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 | |
|---|
| 63 | typedef struct |
|---|
| 64 | { |
|---|
| 65 | int32_t swap_required; |
|---|
| 66 | BAFL_Elf32_Ehdr header; |
|---|
| 67 | BAFL_Elf32_Shdr section_header[BAFL_MAX_SHDR]; |
|---|
| 68 | } ElfInfo; |
|---|
| 69 | |
|---|
| 70 | typedef 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 | |
|---|
| 88 | static 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 | |
|---|
| 96 | BERR_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 | |
|---|
| 367 | static 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 | |
|---|
| 452 | BERR_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 | } |
|---|