1 /* 2 * Copyright (c) 2017 - 2020, Broadcom 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <string.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 12 /* MCU binary image structure: <header> <data> 13 * 14 * Header structure: 15 * <magic-start> 16 * <num-sections> 17 * {<src-offset> <src-size> <dst-addr>}* 18 * <magic-end> 19 * 20 * MCU data (<data>) consists of several sections of code/data, to be 21 * installed (copied) into MCU memories. 22 * Header (<header>) gives information about sections contained in <data>. 23 * 24 * The installer code iterates over sections in MCU binary. 25 * For each section, it copies the section into MCU memory. 26 * 27 * The header contains: 28 * - <magic-start> - 32-bit magic number to mark header start 29 * - <num-sections> - number of sections in <data> 30 * - <num-sections> tuples. Each tuple describes a section. 31 * A tuple contains three 32-bit words. 32 * - <magic-end> - 32-bit magic number to mark header end 33 * 34 * Each section is describes by a tuple, consisting of three 32-bit words: 35 * - offset of section within MCU binary (relative to beginning of <data>) 36 * - section size (in bytes) in MCU binary 37 * - target address (in MCU memory). Section is copied to this location. 38 * 39 * All fields are 32-bit unsigned integers in little endian format. 40 * All sizes are assumed to be 32-bit aligned. 41 */ 42 43 #define SCP_BIN_HEADER_MAGIC_START 0xfa587D01 44 #define SCP_BIN_HEADER_MAGIC_END 0xf3e06a85 45 46 int download_scp_patch(void *image, unsigned int image_size) 47 { 48 unsigned int *pheader = (unsigned int *)(image); 49 unsigned int header_size; 50 unsigned char *pdata; 51 void *dest; 52 unsigned int num_sections; 53 unsigned int section_src_offset; 54 unsigned int section_size; 55 56 if (pheader && (pheader[0] != SCP_BIN_HEADER_MAGIC_START)) { 57 ERROR("SCP: Could not find SCP header.\n"); 58 return -1; 59 } 60 61 num_sections = pheader[1]; 62 INFO("...Number of sections: %d\n", num_sections); 63 header_size = 4 * (1 + 1 + 3 * num_sections + 1); 64 65 if (image_size < header_size) { 66 ERROR("SCP: Wrong size.\n"); 67 return -1; 68 } 69 70 if (*(pheader + header_size/4 - 1) != SCP_BIN_HEADER_MAGIC_END) { 71 ERROR("SCP: Could not find SCP footer.\n"); 72 return -1; 73 } 74 75 VERBOSE("SCP image header validated successfully\n"); 76 pdata = (unsigned char *)pheader + header_size; 77 78 for (pheader += 2; num_sections > 0; num_sections--) { 79 80 section_src_offset = pheader[0]; 81 section_size = pheader[1]; 82 dest = (void *)(unsigned long)pheader[2]; 83 84 INFO("section: src:0x%x, size:%d, dst:0x%x\n", 85 section_src_offset, section_size, pheader[2]); 86 87 if ((section_src_offset + section_size) > image_size) { 88 ERROR("SCP: Section points to outside of patch.\n"); 89 return -1; 90 } 91 92 /* copy from source to target section */ 93 memcpy(dest, pdata + section_src_offset, section_size); 94 flush_dcache_range((uintptr_t)dest, section_size); 95 96 /* next section */ 97 pheader += 3; 98 } 99 return 0; 100 } 101