|
27 | 27 | #include "printf.h" |
28 | 28 | #include "string.h" |
29 | 29 | #include "elf.h" |
| 30 | +#include "hal.h" |
30 | 31 |
|
31 | 32 | #ifdef ARCH_PPC |
32 | 33 | #include "hal/nxp_ppc.h" |
|
43 | 44 | #endif |
44 | 45 |
|
45 | 46 |
|
| 47 | +#ifdef MMU |
46 | 48 | /* Loader for elf32 or elf64 format program headers |
47 | 49 | * Returns the entry point function |
48 | 50 | */ |
@@ -143,11 +145,262 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb) |
143 | 145 |
|
144 | 146 | return 0; |
145 | 147 | } |
| 148 | +#endif /* MMU */ |
146 | 149 |
|
147 | | -int elf_load_image(uint8_t *image, uintptr_t *entry) |
| 150 | +#if 0 |
| 151 | +/** |
| 152 | + * @brief Compute the scattered hash by hashing PT_LOAD segments at their XIP |
| 153 | + * addresses. Note: This function assumes that the destination addresses for elf |
| 154 | + * loading have the same access patterns as the memory represented by img. |
| 155 | + * (e.g. if BOOT partition is external, then reads/writes to the load address |
| 156 | + * will use ext_flash_read/ext_flash_write. |
| 157 | + * |
| 158 | + * @param img Pointer to the wolfBoot image |
| 159 | + * @param hash Buffer to store the computed hash (must be at least |
| 160 | + * WOLFBOOT_SHA_DIGEST_SIZE bytes) |
| 161 | + * @return 0 on success, negative value on error |
| 162 | + */ |
| 163 | +static int wolfBoot_compute_scattered_hash(struct wolfBoot_image *img, uint8_t *hash) |
148 | 164 | { |
| 165 | + uint8_t elf_header_buf[sizeof(elf64_header)]; |
| 166 | + uint8_t program_header_buf[sizeof(elf64_program_header)]; |
| 167 | + elf32_header* h32; |
| 168 | + elf64_header* h64; |
| 169 | + uint16_t entry_count, entry_size; |
| 170 | + uint32_t ph_offset; |
| 171 | + int is_elf32, is_le, i; |
| 172 | +#if defined(WOLFBOOT_HASH_SHA256) |
| 173 | + wc_Sha256 sha256_ctx; |
| 174 | +#elif defined(WOLFBOOT_HASH_SHA384) |
| 175 | + wc_Sha384 sha384_ctx; |
| 176 | +#elif defined(WOLFBOOT_HASH_SHA3_384) |
| 177 | + wc_Sha3 sha3_384_ctx; |
| 178 | +#endif |
| 179 | + |
| 180 | +#ifdef EXT_FLASH |
| 181 | + if (PART_IS_EXT(img)) { |
| 182 | + /* Read ELF header from external flash */ |
| 183 | + ext_flash_check_read((uintptr_t)(img->fw_base), elf_header_buf, sizeof(elf64_header)); |
| 184 | + } else |
| 185 | +#endif |
| 186 | + { |
| 187 | + memcpy(elf_header_buf, (void*)(img->fw_base), sizeof(elf64_header)); |
| 188 | + } |
| 189 | + |
| 190 | + h32 = (elf32_header*)elf_header_buf; |
| 191 | + h64 = (elf64_header*)elf_header_buf; |
| 192 | + |
| 193 | + /* Verify ELF header */ |
| 194 | + if (memcmp(h32->ident, ELF_IDENT_STR, 4) != 0) { |
| 195 | + return -1; /* not valid header identifier */ |
| 196 | + } |
| 197 | + |
| 198 | + /* Load class and endianess */ |
| 199 | + is_elf32 = (h32->ident[4] == ELF_CLASS_32); |
| 200 | + is_le = (h32->ident[5] == ELF_ENDIAN_LITTLE); |
| 201 | + (void)is_le; |
| 202 | + |
| 203 | + /* Initialize hash context */ |
| 204 | +#if defined(WOLFBOOT_HASH_SHA256) |
| 205 | + wc_InitSha256(&sha256_ctx); |
| 206 | +#elif defined(WOLFBOOT_HASH_SHA384) |
| 207 | + wc_InitSha384(&sha384_ctx); |
| 208 | +#elif defined(WOLFBOOT_HASH_SHA3_384) |
| 209 | + wc_Sha3_384_Init(&sha3_384_ctx, NULL, INVALID_DEVID); |
| 210 | +#endif |
| 211 | + |
| 212 | + /* Get program headers info */ |
| 213 | + ph_offset = is_elf32 ? GET32(h32->ph_offset) : GET32(h64->ph_offset); |
| 214 | + entry_size = is_elf32 ? GET16(h32->ph_entry_size) : GET16(h64->ph_entry_size); |
| 215 | + entry_count = is_elf32 ? GET16(h32->ph_entry_count) : GET16(h64->ph_entry_count); |
| 216 | + |
| 217 | + /* Hash each loadable segment directly from its physical address */ |
| 218 | + for (i = 0; i < entry_count; i++) { |
| 219 | + elf32_program_header* phdr32; |
| 220 | + elf64_program_header* phdr64; |
| 221 | + uint32_t type; |
| 222 | + uintptr_t paddr; |
| 223 | + uintptr_t file_size; |
| 224 | + |
| 225 | + /* Read program header into buffer */ |
| 226 | +#ifdef EXT_FLASH |
| 227 | + if (PART_IS_EXT(img)) { |
| 228 | + ext_flash_check_read((uintptr_t)(img->fw_base) + ph_offset + (i * entry_size), |
| 229 | + program_header_buf, entry_size); |
| 230 | + } else |
| 231 | +#endif |
| 232 | + { |
| 233 | + memcpy(program_header_buf, |
| 234 | + (uint8_t*)(img->fw_base) + ph_offset + (i * entry_size), |
| 235 | + entry_size); |
| 236 | + } |
| 237 | + |
| 238 | + |
| 239 | + phdr32 = (elf32_program_header*)program_header_buf; |
| 240 | + phdr64 = (elf64_program_header*)program_header_buf; |
| 241 | + type = (is_elf32 ? GET32(phdr32->type) : GET32(phdr64->type)); |
| 242 | + paddr = (is_elf32 ? GET32(phdr32->paddr) : GET64(phdr64->paddr)); |
| 243 | + file_size = (is_elf32 ? GET32(phdr32->file_size) : GET64(phdr64->file_size)); |
| 244 | + |
| 245 | + /* Only hash PT_LOAD segments with non-zero size */ |
| 246 | + if (type == ELF_PT_LOAD && file_size > 0) { |
| 247 | +#ifdef DEBUG_ELF |
| 248 | + wolfBoot_printf("Hashing segment at %p (%d bytes)\r\n", (void*)paddr, (uint32_t)file_size); |
| 249 | +#endif |
| 250 | + /* Hash the segment data from physical address in blocks */ |
| 251 | + uint32_t pos = 0; |
| 252 | + while (pos < file_size) { |
| 253 | + uint8_t *block; |
| 254 | + uint32_t blksz = WOLFBOOT_SHA_BLOCK_SIZE; |
| 255 | + |
| 256 | + if (pos + blksz > file_size) { |
| 257 | + blksz = file_size - pos; |
| 258 | + } |
| 259 | + |
| 260 | + block = get_sha_block_ptr(img, (const uint8_t *)(paddr + pos)); |
| 261 | + if (block == NULL) { |
| 262 | + return -1; |
| 263 | + } |
| 264 | + |
| 265 | +#if defined(WOLFBOOT_HASH_SHA256) |
| 266 | + wc_Sha256Update(&sha256_ctx, block, blksz); |
| 267 | +#elif defined(WOLFBOOT_HASH_SHA384) |
| 268 | + wc_Sha384Update(&sha384_ctx, block, blksz); |
| 269 | +#elif defined(WOLFBOOT_HASH_SHA3_384) |
| 270 | + wc_Sha3_384_Update(&sha3_384_ctx, block, blksz); |
| 271 | +#endif |
| 272 | + pos += blksz; |
| 273 | + } |
| 274 | + } |
| 275 | + } |
| 276 | + |
| 277 | + /* Finalize hash */ |
| 278 | +#if defined(WOLFBOOT_HASH_SHA256) |
| 279 | + wc_Sha256Final(&sha256_ctx, hash); |
| 280 | +#elif defined(WOLFBOOT_HASH_SHA384) |
| 281 | + wc_Sha384Final(&sha384_ctx, hash); |
| 282 | +#elif defined(WOLFBOOT_HASH_SHA3_384) |
| 283 | + wc_Sha3_384_Final(&sha3_384_ctx, hash); |
| 284 | +#endif |
| 285 | + |
| 286 | + return 0; |
| 287 | +} |
| 288 | +#endif |
| 289 | + |
| 290 | +int elf_store_image_scattered(const unsigned char *image, unsigned long *entry_out, int ext_flash) { |
| 291 | + const unsigned char *ident; |
| 292 | + int is_elf32; |
| 293 | + unsigned short entry_count; |
| 294 | + unsigned short entry_size; |
| 295 | + unsigned long entry_off; |
| 296 | + int i; |
| 297 | + |
| 298 | + ident = image; |
| 299 | + |
| 300 | + |
| 301 | + /* Verify ELF header */ |
| 302 | + if (memcmp(ident, ELF_IDENT_STR, 4) != 0) { |
| 303 | + return -1; /* not valid header identifier */ |
| 304 | + } |
| 305 | + |
| 306 | + is_elf32 = (ident[ELF_CLASS_OFF] == ELF_CLASS_32); |
| 307 | + |
| 308 | + if (is_elf32) { |
| 309 | + const elf32_header *eh; |
| 310 | + const elf32_program_header *ph; |
| 311 | + |
| 312 | + eh = (const elf32_header *)image; |
| 313 | + entry_count = eh->ph_entry_count; |
| 314 | + entry_size = eh->ph_entry_size; |
| 315 | + entry_off = eh->ph_offset; |
| 316 | + *entry_out = (unsigned long)eh->entry; |
| 317 | + |
| 318 | + ph = (const elf32_program_header *)(image + entry_off); |
| 319 | + for (i = 0; i < entry_count; ++i) { |
| 320 | + unsigned long paddr; |
| 321 | + unsigned long filesz; |
| 322 | + unsigned long offset; |
| 323 | + |
| 324 | + if (ph[i].type != ELF_PT_LOAD) |
| 325 | + continue; |
| 326 | + |
| 327 | + paddr = (unsigned long)ph[i].paddr; |
| 328 | + offset = (unsigned long)ph[i].offset; |
| 329 | + filesz = (unsigned long)ph[i].file_size; |
| 330 | +#if 0 |
| 331 | +#ifdef EXT_FLASH |
| 332 | + if (ext_flash) { |
| 333 | + ext_flash_unlock(); |
| 334 | + ext_flash_erase(paddr, filesz); |
| 335 | + ext_flash_write(paddr, image + offset, filesz); |
| 336 | + ext_flash_lock(); |
| 337 | + } |
| 338 | + else |
| 339 | +#endif |
| 340 | + { |
| 341 | + hal_flash_unlock(); |
| 342 | + hal_flash_erase(paddr, filesz); |
| 343 | + hal_flash_write(paddr, image + offset, filesz); |
| 344 | + hal_flash_lock(); |
| 345 | + } |
| 346 | +#endif |
| 347 | + } |
| 348 | + } else if (ident[ELF_CLASS_OFF] == ELF_CLASS_64) { |
| 349 | + const elf64_header *eh; |
| 350 | + const elf64_program_header *ph; |
| 351 | + |
| 352 | + eh = (const elf64_header *)image; |
| 353 | + entry_count = eh->ph_entry_count; |
| 354 | + entry_size = eh->ph_entry_size; |
| 355 | + entry_off = eh->ph_offset; |
| 356 | + *entry_out = (unsigned long)eh->entry; |
| 357 | + |
| 358 | + ph = (const elf64_program_header *)(image + entry_off); |
| 359 | + for (i = 0; i < entry_count; ++i) { |
| 360 | + unsigned long paddr; |
| 361 | + unsigned long filesz; |
| 362 | + unsigned long offset; |
| 363 | + |
| 364 | + if (ph[i].type != ELF_PT_LOAD) |
| 365 | + continue; |
| 366 | + |
| 367 | + paddr = (unsigned long)ph[i].paddr; |
| 368 | + offset = (unsigned long)ph[i].offset; |
| 369 | + filesz = (unsigned long)ph[i].file_size; |
| 370 | +#if 0 |
| 371 | +#ifdef EXT_FLASH |
| 372 | + if (ext_flash) { |
| 373 | + ext_flash_unlock(); |
| 374 | + ext_flash_erase(paddr, filesz); |
| 375 | + ext_flash_write(paddr, image + offset, filesz); |
| 376 | + ext_flash_lock(); |
| 377 | + } |
| 378 | + else |
| 379 | +#endif |
| 380 | + { |
| 381 | + hal_flash_unlock(); |
| 382 | + hal_flash_erase(paddr, filesz); |
| 383 | + hal_flash_write(paddr, image + offset, filesz); |
| 384 | + hal_flash_lock(); |
| 385 | + } |
| 386 | +#endif |
| 387 | + } |
| 388 | + } else { |
| 389 | + /* Invalid elf header. */ |
| 390 | + return -1; |
| 391 | + } |
| 392 | + |
| 393 | + return 0; |
| 394 | +} |
| 395 | + |
149 | 396 |
|
| 397 | +int elf_load_image(uint8_t *image, uintptr_t *entry, int ext_flash) |
| 398 | +{ |
| 399 | +#ifdef MMU |
150 | 400 | return elf_load_image_mmu(image, entry, NULL); |
| 401 | +#else |
| 402 | + return elf_store_image_scattered(image, entry, ext_flash); |
| 403 | +#endif |
151 | 404 | } |
152 | 405 |
|
153 | 406 | #endif /* WOLFBOOT_ELF */ |
0 commit comments