summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/sbinfo/elf.c74
-rw-r--r--utils/sbinfo/elf.h39
-rw-r--r--utils/sbinfo/sbinfo.c59
3 files changed, 129 insertions, 43 deletions
diff --git a/utils/sbinfo/elf.c b/utils/sbinfo/elf.c
index 0fe6792e1d..6c5ed2e762 100644
--- a/utils/sbinfo/elf.c
+++ b/utils/sbinfo/elf.c
@@ -57,13 +57,16 @@ void elf_add_fill_section(struct elf_params_t *params,
57void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) 57void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
58{ 58{
59 Elf32_Ehdr ehdr; 59 Elf32_Ehdr ehdr;
60 uint32_t phoff = sizeof(Elf32_Ehdr);
61 uint32_t phentsize = sizeof(Elf32_Phdr);
62 uint32_t phnum = 0; 60 uint32_t phnum = 0;
63 uint32_t shstrndx = SHN_UNDEF;
64 struct elf_section_t *sec = params->first_section; 61 struct elf_section_t *sec = params->first_section;
65 uint32_t offset = 0; 62 uint32_t offset = 0;
66 Elf32_Phdr phdr; 63 Elf32_Phdr phdr;
64 Elf32_Shdr shdr;
65 memset(&ehdr, 0, EI_NIDENT);
66
67 uint32_t bss_strtbl = 0;
68 uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1;
69 uint32_t strtbl_size = text_strtbl + strlen(".text") + 1;
67 70
68 while(sec) 71 while(sec)
69 { 72 {
@@ -77,7 +80,8 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
77 sec = sec->next; 80 sec = sec->next;
78 } 81 }
79 82
80 memset(&ehdr, 0, EI_NIDENT); 83 uint32_t strtbl_offset = offset;
84
81 ehdr.e_ident[EI_MAG0] = ELFMAG0; 85 ehdr.e_ident[EI_MAG0] = ELFMAG0;
82 ehdr.e_ident[EI_MAG1] = ELFMAG1; 86 ehdr.e_ident[EI_MAG1] = ELFMAG1;
83 ehdr.e_ident[EI_MAG2] = ELFMAG2; 87 ehdr.e_ident[EI_MAG2] = ELFMAG2;
@@ -91,25 +95,28 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
91 ehdr.e_machine = EM_ARM; 95 ehdr.e_machine = EM_ARM;
92 ehdr.e_version = EV_CURRENT; 96 ehdr.e_version = EV_CURRENT;
93 ehdr.e_entry = params->start_addr; 97 ehdr.e_entry = params->start_addr;
94 ehdr.e_phoff = phoff;
95 ehdr.e_shoff = 0;
96 ehdr.e_flags = 0; 98 ehdr.e_flags = 0;
97 if(params->has_start_addr) 99 if(params->has_start_addr)
98 ehdr.e_flags |= EF_ARM_HASENTRY; 100 ehdr.e_flags |= EF_ARM_HASENTRY;
99 ehdr.e_ehsize = sizeof ehdr; 101 ehdr.e_ehsize = sizeof ehdr;
100 ehdr.e_phentsize = phentsize; 102 ehdr.e_phentsize = sizeof phdr;
101 ehdr.e_phnum = phnum; 103 ehdr.e_phnum = phnum;
102 ehdr.e_shentsize = 0; 104 ehdr.e_shentsize = sizeof shdr;
103 ehdr.e_shnum = 0; 105 ehdr.e_shnum = phnum + 1;
104 ehdr.e_shstrndx = shstrndx; 106 ehdr.e_shstrndx = ehdr.e_shnum - 1;
107 ehdr.e_phoff = ehdr.e_ehsize;
108 ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize;
105 109
106 write(user, 0, &ehdr, sizeof ehdr); 110 write(user, 0, &ehdr, sizeof ehdr);
107 111
112 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
113 ehdr.e_shnum * ehdr.e_shentsize;
114
108 sec = params->first_section; 115 sec = params->first_section;
109 offset = phoff; 116 offset = ehdr.e_phoff;
110 while(sec) 117 while(sec)
111 { 118 {
112 sec->offset += phoff + phnum * phentsize; 119 sec->offset += data_offset;
113 120
114 phdr.p_type = PT_LOAD; 121 phdr.p_type = PT_LOAD;
115 if(sec->type == EST_LOAD) 122 if(sec->type == EST_LOAD)
@@ -133,12 +140,55 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
133 } 140 }
134 141
135 sec = params->first_section; 142 sec = params->first_section;
143 offset = ehdr.e_shoff;
144 while(sec)
145 {
146 shdr.sh_name = text_strtbl;
147 if(sec->type == EST_LOAD)
148 shdr.sh_type = SHT_PROGBITS;
149 else
150 shdr.sh_type = SHT_NOBITS;
151 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
152 shdr.sh_addr = sec->addr;
153 shdr.sh_offset = sec->offset;
154 shdr.sh_size = sec->size;
155 shdr.sh_link = SHN_UNDEF;
156 shdr.sh_info = 0;
157 shdr.sh_addralign = 1;
158 shdr.sh_entsize = 0;
159
160 write(user, offset, &shdr, sizeof shdr);
161
162 offset += sizeof(Elf32_Shdr);
163 sec = sec->next;
164 }
165
166 {
167 shdr.sh_name = bss_strtbl;
168 shdr.sh_type = SHT_STRTAB;
169 shdr.sh_flags = 0;
170 shdr.sh_addr = 0;
171 shdr.sh_offset = strtbl_offset + data_offset;
172 shdr.sh_size = strtbl_size;
173 shdr.sh_link = SHN_UNDEF;
174 shdr.sh_info = 0;
175 shdr.sh_addralign = 1;
176 shdr.sh_entsize = 0;
177
178 write(user, offset, &shdr, sizeof shdr);
179
180 offset += sizeof(Elf32_Shdr);
181 }
182
183 sec = params->first_section;
136 while(sec) 184 while(sec)
137 { 185 {
138 if(sec->type == EST_LOAD) 186 if(sec->type == EST_LOAD)
139 write(user, sec->offset, sec->section, sec->size); 187 write(user, sec->offset, sec->section, sec->size);
140 sec = sec->next; 188 sec = sec->next;
141 } 189 }
190
191 write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size);
142} 192}
143 193
144bool elf_is_empty(struct elf_params_t *params) 194bool elf_is_empty(struct elf_params_t *params)
diff --git a/utils/sbinfo/elf.h b/utils/sbinfo/elf.h
index eb990389d9..d2bf210c5c 100644
--- a/utils/sbinfo/elf.h
+++ b/utils/sbinfo/elf.h
@@ -80,6 +80,45 @@ typedef struct
80 80
81typedef struct 81typedef struct
82{ 82{
83 Elf32_Word sh_name; /* Section name (string tbl index) */
84 Elf32_Word sh_type; /* Section type */
85 Elf32_Word sh_flags; /* Section flags */
86 Elf32_Addr sh_addr; /* Section virtual addr at execution */
87 Elf32_Off sh_offset; /* Section file offset */
88 Elf32_Word sh_size; /* Section size in bytes */
89 Elf32_Word sh_link; /* Link to another section */
90 Elf32_Word sh_info; /* Additional section information */
91 Elf32_Word sh_addralign; /* Section alignment */
92 Elf32_Word sh_entsize; /* Entry size if section holds table */
93}Elf32_Shdr;
94
95#define SHT_NULL 0 /* Section header table entry unused */
96#define SHT_PROGBITS 1 /* Program data */
97#define SHT_SYMTAB 2 /* Symbol table */
98#define SHT_STRTAB 3 /* String table */
99#define SHT_RELA 4 /* Relocation entries with addends */
100#define SHT_HASH 5 /* Symbol hash table */
101#define SHT_DYNAMIC 6 /* Dynamic linking information */
102#define SHT_NOTE 7 /* Notes */
103#define SHT_NOBITS 8 /* Program space with no data (bss) */
104#define SHT_REL 9 /* Relocation entries, no addends */
105#define SHT_SHLIB 10 /* Reserved */
106#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
107#define SHT_INIT_ARRAY 14 /* Array of constructors */
108#define SHT_FINI_ARRAY 15 /* Array of destructors */
109#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
110#define SHT_GROUP 17 /* Section group */
111#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
112#define SHT_NUM 19 /* Number of defined types. */
113
114#define SHF_WRITE (1 << 0) /* Writable */
115#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
116#define SHF_EXECINSTR (1 << 2) /* Executable */
117#define SHF_MERGE (1 << 4) /* Might be merged */
118#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
119
120typedef struct
121{
83 Elf32_Word p_type; /* Segment type */ 122 Elf32_Word p_type; /* Segment type */
84 Elf32_Off p_offset; /* Segment file offset */ 123 Elf32_Off p_offset; /* Segment file offset */
85 Elf32_Addr p_vaddr; /* Segment virtual address */ 124 Elf32_Addr p_vaddr; /* Segment virtual address */
diff --git a/utils/sbinfo/sbinfo.c b/utils/sbinfo/sbinfo.c
index d065fc9eed..710c481deb 100644
--- a/utils/sbinfo/sbinfo.c
+++ b/utils/sbinfo/sbinfo.c
@@ -63,8 +63,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
63 63
64/* byte swapping */ 64/* byte swapping */
65#define get32le(a) ((uint32_t) \ 65#define get32le(a) ((uint32_t) \
66 ( buf[a+3] << 24 | buf[a+2] << 16 | buf[a+1] << 8 | buf[a] )) 66 ( g_buf[a+3] << 24 | g_buf[a+2] << 16 | g_buf[a+1] << 8 | g_buf[a] ))
67#define get16le(a) ((uint16_t)( buf[a+1] << 8 | buf[a] )) 67#define get16le(a) ((uint16_t)( g_buf[a+1] << 8 | g_buf[a] ))
68 68
69/* all blocks are sized as a multiple of 0x1ff */ 69/* all blocks are sized as a multiple of 0x1ff */
70#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff) 70#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
@@ -74,8 +74,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
74 74
75/* globals */ 75/* globals */
76 76
77size_t sz; /* file size */ 77size_t g_sz; /* file size */
78uint8_t *buf; /* file content */ 78uint8_t *g_buf; /* file content */
79#define PREFIX_SIZE 128 79#define PREFIX_SIZE 128
80char out_prefix[PREFIX_SIZE]; 80char out_prefix[PREFIX_SIZE];
81const char *key_file; 81const char *key_file;
@@ -129,25 +129,23 @@ void *xmalloc(size_t s) /* malloc helper, used in elf.c */
129static char getchr(int offset) 129static char getchr(int offset)
130{ 130{
131 char c; 131 char c;
132 c = buf[offset]; 132 c = g_buf[offset];
133 return isprint(c) ? c : '_'; 133 return isprint(c) ? c : '_';
134} 134}
135 135
136static void getstrle(char string[], int offset) 136static void getstrle(char string[], int offset)
137{ 137{
138 int i; 138 int i;
139 for (i = 0; i < 4; i++) { 139 for (i = 0; i < 4; i++)
140 string[i] = getchr(offset + 3 - i); 140 string[i] = getchr(offset + 3 - i);
141 }
142 string[4] = 0; 141 string[4] = 0;
143} 142}
144 143
145static void getstrbe(char string[], int offset) 144static void getstrbe(char string[], int offset)
146{ 145{
147 int i; 146 int i;
148 for (i = 0; i < 4; i++) { 147 for (i = 0; i < 4; i++)
149 string[i] = getchr(offset + i); 148 string[i] = getchr(offset + i);
150 }
151 string[4] = 0; 149 string[4] = 0;
152} 150}
153 151
@@ -155,9 +153,8 @@ static void printhex(int offset, int len)
155{ 153{
156 int i; 154 int i;
157 155
158 for (i = 0; i < len; i++) { 156 for (i = 0; i < len; i++)
159 printf("%02X ", buf[offset + i]); 157 printf("%02X ", g_buf[offset + i]);
160 }
161 printf("\n"); 158 printf("\n");
162} 159}
163 160
@@ -222,7 +219,7 @@ static key_array_t read_keys(int num_keys)
222 bugp("key file stat() failed"); 219 bugp("key file stat() failed");
223 size = st.st_size; 220 size = st.st_size;
224 char *buf = xmalloc(size); 221 char *buf = xmalloc(size);
225 if(read(fd,buf,sz)!=(ssize_t)size) 222 if(read(fd, buf, size) != (ssize_t)size)
226 bugp("reading key file"); 223 bugp("reading key file");
227 close(fd); 224 close(fd);
228 225
@@ -417,13 +414,13 @@ static void extract(unsigned long filesize)
417 printf("Basic info:\n"); 414 printf("Basic info:\n");
418 color(GREEN); 415 color(GREEN);
419 printf("\tHeader SHA-1: "); 416 printf("\tHeader SHA-1: ");
420 byte *hdr_sha1 = &buf[0]; 417 byte *hdr_sha1 = &g_buf[0];
421 color(YELLOW); 418 color(YELLOW);
422 print_sha1(hdr_sha1); 419 print_sha1(hdr_sha1);
423 /* Check SHA1 sum */ 420 /* Check SHA1 sum */
424 byte computed_sha1[20]; 421 byte computed_sha1[20];
425 sha_1_init(&sha_1_params); 422 sha_1_init(&sha_1_params);
426 sha_1_update(&sha_1_params, &buf[0x14], 0x4C); 423 sha_1_update(&sha_1_params, &g_buf[0x14], 0x4C);
427 sha_1_finish(&sha_1_params); 424 sha_1_finish(&sha_1_params);
428 sha_1_output(&sha_1_params, computed_sha1); 425 sha_1_output(&sha_1_params, computed_sha1);
429 color(RED); 426 color(RED);
@@ -480,7 +477,7 @@ static void extract(unsigned long filesize)
480 if(num_enc > 0) 477 if(num_enc > 0)
481 { 478 {
482 keys = read_keys(num_enc); 479 keys = read_keys(num_enc);
483 color(BLUE), 480 color(BLUE);
484 printf("Encryption data\n"); 481 printf("Encryption data\n");
485 for(int i = 0; i < num_enc; i++) 482 for(int i = 0; i < num_enc; i++)
486 { 483 {
@@ -492,14 +489,14 @@ static void extract(unsigned long filesize)
492 printf("\t\tCBC-MAC of headers: "); 489 printf("\t\tCBC-MAC of headers: ");
493 /* copy the cbc mac */ 490 /* copy the cbc mac */
494 byte hdr_cbc_mac[16]; 491 byte hdr_cbc_mac[16];
495 memcpy(hdr_cbc_mac, &buf[0x60 + 16 * num_chunks + 32 * i], 16); 492 memcpy(hdr_cbc_mac, &g_buf[0x60 + 16 * num_chunks + 32 * i], 16);
496 color(YELLOW); 493 color(YELLOW);
497 print_key(hdr_cbc_mac); 494 print_key(hdr_cbc_mac);
498 /* check it */ 495 /* check it */
499 byte computed_cbc_mac[16]; 496 byte computed_cbc_mac[16];
500 byte zero[16]; 497 byte zero[16];
501 memset(zero, 0, 16); 498 memset(zero, 0, 16);
502 cbc_mac(buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1); 499 cbc_mac(g_buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1);
503 color(RED); 500 color(RED);
504 if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0) 501 if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0)
505 printf(" Ok\n"); 502 printf(" Ok\n");
@@ -509,7 +506,7 @@ static void extract(unsigned long filesize)
509 506
510 printf("\t\tEncrypted key : "); 507 printf("\t\tEncrypted key : ");
511 byte (*encrypted_key)[16]; 508 byte (*encrypted_key)[16];
512 encrypted_key = (key_array_t)&buf[0x60 + 16 * num_chunks + 32 * i + 16]; 509 encrypted_key = (key_array_t)&g_buf[0x60 + 16 * num_chunks + 32 * i + 16];
513 color(YELLOW); 510 color(YELLOW);
514 print_key(*encrypted_key); 511 print_key(*encrypted_key);
515 printf("\n"); 512 printf("\n");
@@ -517,7 +514,7 @@ static void extract(unsigned long filesize)
517 /* decrypt */ 514 /* decrypt */
518 byte decrypted_key[16]; 515 byte decrypted_key[16];
519 byte iv[16]; 516 byte iv[16];
520 memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ 517 memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
521 cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0); 518 cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0);
522 printf("\t\tDecrypted key : "); 519 printf("\t\tDecrypted key : ");
523 color(YELLOW); 520 color(YELLOW);
@@ -571,9 +568,9 @@ static void extract(unsigned long filesize)
571 /* save it */ 568 /* save it */
572 byte *sec = xmalloc(size); 569 byte *sec = xmalloc(size);
573 if(encrypted) 570 if(encrypted)
574 cbc_mac(buf + pos, sec, size / 16, real_key, buf, NULL, 0); 571 cbc_mac(g_buf + pos, sec, size / 16, real_key, g_buf, NULL, 0);
575 else 572 else
576 memcpy(sec, buf + pos, size); 573 memcpy(sec, g_buf + pos, size);
577 574
578 extract_section(data_sec, name, sec, size, "\t\t\t"); 575 extract_section(data_sec, name, sec, size, "\t\t\t");
579 free(sec); 576 free(sec);
@@ -590,16 +587,16 @@ static void extract(unsigned long filesize)
590 printf("\t\t"); 587 printf("\t\t");
591 printhex(filesize - 16, 16); 588 printhex(filesize - 16, 16);
592 /* decrypt it */ 589 /* decrypt it */
593 byte *encrypted_block = &buf[filesize - 32]; 590 byte *encrypted_block = &g_buf[filesize - 32];
594 byte decrypted_block[32]; 591 byte decrypted_block[32];
595 cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0); 592 cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0);
596 color(GREEN); 593 color(GREEN);
597 printf("\tDecrypted SHA-1:\n\t\t"); 594 printf("\tDecrypted SHA-1:\n\t\t");
598 color(YELLOW); 595 color(YELLOW);
599 print_sha1(decrypted_block); 596 print_sha1(decrypted_block);
600 /* check it */ 597 /* check it */
601 sha_1_init(&sha_1_params); 598 sha_1_init(&sha_1_params);
602 sha_1_update(&sha_1_params, buf, filesize - 32); 599 sha_1_update(&sha_1_params, g_buf, filesize - 32);
603 sha_1_finish(&sha_1_params); 600 sha_1_finish(&sha_1_params);
604 sha_1_output(&sha_1_params, computed_sha1); 601 sha_1_output(&sha_1_params, computed_sha1);
605 color(RED); 602 color(RED);
@@ -621,17 +618,17 @@ int main(int argc, const char **argv)
621 else 618 else
622 strcpy(out_prefix, ""); 619 strcpy(out_prefix, "");
623 620
624 if( (fd = open(argv[1],O_RDONLY)) == -1 ) 621 if( (fd = open(argv[1], O_RDONLY)) == -1 )
625 bugp("opening firmware failed"); 622 bugp("opening firmware failed");
626 623
627 key_file = argv[2]; 624 key_file = argv[2];
628 625
629 if(fstat(fd,&st) == -1) 626 if(fstat(fd, &st) == -1)
630 bugp("firmware stat() failed"); 627 bugp("firmware stat() failed");
631 sz = st.st_size; 628 g_sz = st.st_size;
632 629
633 buf=xmalloc(sz); 630 g_buf = xmalloc(g_sz);
634 if(read(fd,buf,sz)!=(ssize_t)sz) /* load the whole file into memory */ 631 if(read(fd, g_buf, g_sz) != (ssize_t)g_sz) /* load the whole file into memory */
635 bugp("reading firmware"); 632 bugp("reading firmware");
636 633
637 close(fd); 634 close(fd);
@@ -641,6 +638,6 @@ int main(int argc, const char **argv)
641 638
642 color(OFF); 639 color(OFF);
643 640
644 free(buf); 641 free(g_buf);
645 return 0; 642 return 0;
646} 643}