Merge "sysupgrade: Add support to process 64 bit image"
diff --git a/include/elf.h b/include/elf.h
index a35e085..a275c91 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -113,6 +113,25 @@
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 @@
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 */
diff --git a/tools/sysupgrade.c b/tools/sysupgrade.c
index 368a4f1..58c9157 100644
--- a/tools/sysupgrade.c
+++ b/tools/sysupgrade.c
@@ -142,11 +142,22 @@
elf = (Elf32_Ehdr *)fp;
if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
- (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
- (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
+ /* 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)) {
- (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
- (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
+ 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 @@
}
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 @@
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 @@
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";
@@ -847,6 +947,62 @@
}
/**
+ * 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 @@
{
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 @@
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 @@
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 @@
return 0;
}
strncpy(hw_file, tmp, 32);
- free(tmp);
free(sw_id_str);
free(hw_id_str);
diff --git a/tools/sysupgrade.h b/tools/sysupgrade.h
index b0be748..081818b 100644
--- a/tools/sysupgrade.h
+++ b/tools/sysupgrade.h
@@ -88,12 +88,14 @@
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 *);