mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
sysupgrade: Add support to process 64 bit image
The existing sysupgrade treats all images as 32-bit image. This change adds a check to signify the image class and adds functions to process the headers respectively. Change-Id: I04040fdc6e1a9c6c2df2407cd4b26dddaf4a008c Signed-off-by: Pavithra Palanisamy <pavip@codeaurora.org>
This commit is contained in:
parent
453d3d213b
commit
fb8e307bbc
3 changed files with 200 additions and 14 deletions
|
|
@ -113,6 +113,25 @@ typedef struct elfhdr{
|
|||
header string table" entry offset */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
/*ELF64 Header */
|
||||
typedef struct elf64hdr{
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
|
||||
Elf64_Half e_type; /* object file type */
|
||||
Elf64_Half e_machine; /* machine */
|
||||
Elf64_Word e_version; /* object file version */
|
||||
Elf64_Addr e_entry; /* virtual entry point */
|
||||
Elf64_Off e_phoff; /* program header table offset */
|
||||
Elf64_Off e_shoff; /* section header table offset */
|
||||
Elf64_Word e_flags; /* processor-specific flags */
|
||||
Elf64_Half e_ehsize; /* ELF header size */
|
||||
Elf64_Half e_phentsize; /* program header entry size */
|
||||
Elf64_Half e_phnum; /* number of program header entries */
|
||||
Elf64_Half e_shentsize; /* section header entry size */
|
||||
Elf64_Half e_shnum; /* number of section header entries */
|
||||
Elf64_Half e_shstrndx; /* section header table's "section
|
||||
header string table" entry offset */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* e_type */
|
||||
#define ET_NONE 0 /* No file type */
|
||||
#define ET_REL 1 /* relocatable file */
|
||||
|
|
@ -411,6 +430,18 @@ typedef struct {
|
|||
Elf32_Word p_align; /* memory alignment */
|
||||
} Elf32_Phdr;
|
||||
|
||||
/* Program Header Elf64*/
|
||||
typedef struct {
|
||||
Elf64_Word p_type; /* segment type */
|
||||
Elf64_Word p_flags; /* flags */
|
||||
Elf64_Off p_offset; /* segment offset */
|
||||
Elf64_Addr p_vaddr; /* virtual address of segment */
|
||||
Elf64_Addr p_paddr; /* physical address - ignored? */
|
||||
Elf64_Xword p_filesz; /* number of bytes in file for seg. */
|
||||
Elf64_Xword p_memsz; /* number of bytes in mem. for seg. */
|
||||
Elf64_Xword p_align; /* memory alignment */
|
||||
} Elf64_Phdr;
|
||||
|
||||
/* Segment types - p_type */
|
||||
#define PT_NULL 0 /* unused */
|
||||
#define PT_LOAD 1 /* loadable segment */
|
||||
|
|
|
|||
|
|
@ -142,11 +142,22 @@ int check_mbn_elf(struct image_section **sec)
|
|||
|
||||
elf = (Elf32_Ehdr *)fp;
|
||||
if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
|
||||
/* EI_CLASS Check for 32/64-bit */
|
||||
if( ((int)(elf->e_ident[4])) == 2) {
|
||||
(*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
|
||||
(*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
|
||||
} else {
|
||||
(*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
|
||||
(*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
|
||||
}
|
||||
} else if (!strncmp((char *)&(((Elf32_Ehdr *)(fp + SBL_NAND_PREAMBLE))->e_ident[1]), "ELF", 3)) {
|
||||
if( ((int)(elf->e_ident[4])) == 2) {
|
||||
(*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
|
||||
(*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
|
||||
} else {
|
||||
(*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
|
||||
(*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
|
||||
}
|
||||
} else {
|
||||
(*sec)->get_sw_id = get_sw_id_from_component_bin;
|
||||
(*sec)->split_components = split_code_signature_cert_from_component_bin;
|
||||
|
|
@ -377,9 +388,8 @@ int get_sw_id_from_component_bin(struct image_section *section)
|
|||
}
|
||||
sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
|
||||
if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
|
||||
printf("Error: Image without version information\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
printf("WARNING: signature certificate size is different\n");
|
||||
// ipq807x has certificate size as dynamic, hence ignore this check
|
||||
}
|
||||
|
||||
cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
|
||||
|
|
@ -452,6 +462,61 @@ int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phd
|
|||
return 1;
|
||||
}
|
||||
|
||||
int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
|
||||
{
|
||||
struct stat sb;
|
||||
int i, fd, version = 0;
|
||||
|
||||
fd = open(bin_file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror(bin_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&sb, 0, sizeof(struct stat));
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
perror("fstat");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (*fp == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*elf = (Elf64_Ehdr *)*fp;
|
||||
while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
|
||||
*fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
|
||||
*elf = (Elf64_Ehdr *)*fp;
|
||||
}
|
||||
|
||||
*phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
|
||||
for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
|
||||
if ((*phdr)->p_flags == HASH_P_FLAG) {
|
||||
*mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
|
||||
if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
|
||||
version = 1;
|
||||
break;
|
||||
} else {
|
||||
printf("Error: Image without version information\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (version != 1) {
|
||||
printf("Error: Image without version information\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
|
||||
* of the hash table segment. Parses the MBN header of hash table segment & checks
|
||||
|
|
@ -487,6 +552,41 @@ int get_sw_id_from_component_bin_elf(struct image_section *section)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
|
||||
* of the hash table segment. Parses the MBN header of hash table segment & checks
|
||||
* total size v/s actual component size. If both differ, it means signature &
|
||||
* certificates are appended at end.
|
||||
* Extract the attestation certificate & read the Subject & retreive the SW_ID.
|
||||
*
|
||||
32_Phdr *phdr;* @bin_file: struct image_section *
|
||||
*/
|
||||
int get_sw_id_from_component_bin_elf64(struct image_section *section)
|
||||
{
|
||||
Elf64_Ehdr *elf;
|
||||
Elf64_Phdr *phdr;
|
||||
Mbn_Hdr *mbn_hdr;
|
||||
uint8_t *fp;
|
||||
int cert_offset;
|
||||
char *sw_version;
|
||||
|
||||
if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
|
||||
printf("Image with version information64\n");
|
||||
sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
|
||||
if (sw_version) {
|
||||
sw_version[8] = '\0';
|
||||
sscanf(sw_version, "%x", §ion->img_version);
|
||||
printf("SW ID:%d\n", section->img_version);
|
||||
free(sw_version);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int find_mtd_part_size(void)
|
||||
{
|
||||
char *mtdname = "kernel";
|
||||
|
|
@ -846,6 +946,62 @@ int split_code_signature_cert_from_component_bin_elf(struct image_section *secti
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* split_code_signature_cert_from_component_bin_elf64 splits the component
|
||||
* binary by splitting into code(including ELF header), signature file &
|
||||
* attenstation certificate.
|
||||
*
|
||||
* @bin_file: char *
|
||||
* @src: char *
|
||||
* @sig: char *
|
||||
* @cert: char *
|
||||
*/
|
||||
int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
|
||||
char **src, char **sig, char **cert)
|
||||
{
|
||||
Elf64_Ehdr *elf;
|
||||
Elf64_Phdr *phdr;
|
||||
Mbn_Hdr *mbn_hdr;
|
||||
uint8_t *fp;
|
||||
int len, sig_offset, cert_offset;
|
||||
|
||||
if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
|
||||
len = sig_offset;
|
||||
*src = malloc((len + 1) * sizeof(char));
|
||||
if (*src == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*src, fp + phdr->p_offset, len);
|
||||
src_size = len;
|
||||
(*src)[len] = '\0';
|
||||
|
||||
*sig = malloc((SIG_SIZE + 1) * sizeof(char));
|
||||
if (*sig == NULL) {
|
||||
free(*src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
|
||||
(*sig)[SIG_SIZE] = '\0';
|
||||
|
||||
cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
|
||||
*cert = malloc((CERT_SIZE + 1) * sizeof(char));
|
||||
if (*cert == NULL) {
|
||||
free(*src);
|
||||
free(*sig);
|
||||
return 0;
|
||||
}
|
||||
memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
|
||||
(*cert)[CERT_SIZE] = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* being used to calculate the image hash
|
||||
*
|
||||
|
|
@ -910,6 +1066,7 @@ char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
|
|||
{
|
||||
int fd;
|
||||
char *file;
|
||||
unsigned long long sw_id, sw_id_be;
|
||||
|
||||
file = mktemp(f_xor);
|
||||
fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
|
|
@ -918,11 +1075,9 @@ char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (write(fd, xor_buffer, sizeof(*xor_buffer)) == -1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sw_id = *xor_buffer;
|
||||
sw_id_be = htobe64(sw_id);
|
||||
write(fd, &sw_id_be, sizeof(sw_id_be));
|
||||
close(fd);
|
||||
return file;
|
||||
}
|
||||
|
|
@ -994,7 +1149,6 @@ int generate_hash(char *cert, char *sw_file, char *hw_file)
|
|||
return 0;
|
||||
}
|
||||
strncpy(sw_file, tmp, 32);
|
||||
free(tmp);
|
||||
|
||||
generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
|
||||
tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
|
||||
|
|
@ -1006,7 +1160,6 @@ int generate_hash(char *cert, char *sw_file, char *hw_file)
|
|||
return 0;
|
||||
}
|
||||
strncpy(hw_file, tmp, 32);
|
||||
free(tmp);
|
||||
|
||||
free(sw_id_str);
|
||||
free(hw_id_str);
|
||||
|
|
|
|||
|
|
@ -88,12 +88,14 @@ int set_local_image_version(struct image_section *);
|
|||
int is_version_check_enabled(void);
|
||||
int get_sw_id_from_component_bin(struct image_section *);
|
||||
int get_sw_id_from_component_bin_elf(struct image_section *);
|
||||
int get_sw_id_from_component_bin_elf64(struct image_section *);
|
||||
int extract_kernel_binary(struct image_section *);
|
||||
int is_image_version_higher(void);
|
||||
int update_version(void);
|
||||
int check_image_version(void);
|
||||
int split_code_signature_cert_from_component_bin(struct image_section *, char **, char **, char **);
|
||||
int split_code_signature_cert_from_component_bin_elf(struct image_section *, char **, char **, char **);
|
||||
int split_code_signature_cert_from_component_bin_elf64(struct image_section *, char **, char **, char **);
|
||||
void generate_swid_ipad(char *, unsigned long long *);
|
||||
void generate_hwid_opad(char *, char *, char *, unsigned long long *);
|
||||
int generate_hash(char *, char *, char *);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue