Add COPYING file
[ps3tools.git] / readself.c
blobfaa4ede841424bc6f6a7b905079e206747a42732
1 // Copyright 2010 Sven Peter <svenpeter@gmail.com>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
5 //
6 // Thanks to xorloser for his selftool!
7 // (see xorloser.com)
8 //
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include "tools.h"
16 static u8 *self;
17 static u8 *elf;
19 static struct elf_hdr ehdr;
21 static int arch64;
22 static u32 meta_offset;
23 static u64 elf_offset;
24 static u64 header_len;
25 static u64 phdr_offset;
26 static u64 shdr_offset;
27 static u64 filesize;
28 static u32 vendorid;
29 static u64 authid;
30 static u64 app_version;
31 static u32 app_type;
32 static u16 sdk_type;
33 static u64 info_offset;
34 static u64 sec_offset;
35 static u64 ver_info;
36 static u64 ctrl_offset;
37 static u64 ctrl_size;
39 static int decrypted = -1;
41 struct id2name_tbl t_sdk_type[] = {
42 {0, "Retail (Type 0)"},
43 {1, "Retail"},
44 {2, "Retail (Type 1)"},
45 {0x8000, "Devkit"},
46 {0, NULL}
49 struct id2name_tbl t_app_type[] = {
50 {1, "level 0"},
51 {2, "level 1"},
52 {3, "level 2"},
53 {4, "application"},
54 {5, "isolated SPU module"},
55 {6, "secure loader"},
56 {8, "NP-DRM application"},
57 {0, NULL}
60 static struct id2name_tbl t_shdr_type[] = {
61 {0, "NULL"},
62 {1, "PROGBITS"},
63 {2, "SYMTAB"},
64 {3, "STRTAB"},
65 {4, "RELA"},
66 {5, "HASH"},
67 {6, "DYNAMIC"},
68 {7, "NOTE"},
69 {8, "NOBITS"},
70 {9, "REL"},
71 {10, "SHLIB"},
72 {11, "DYNSYM"},
73 {12, NULL},
76 static struct id2name_tbl t_elf_type[] = {
77 {ET_NONE, "None"},
78 {ET_REL, "Relocatable file"},
79 {ET_EXEC, "Executable file"},
80 {ET_DYN, "Shared object file"},
81 {ET_CORE, "Core file"},
82 {0, NULL}
85 static struct id2name_tbl t_elf_machine[] = {
86 {20, "PowerPC"},
87 {21, "PowerPC64"},
88 {23, "SPE"},
89 {0, NULL}
93 static struct id2name_tbl t_phdr_type[] = {
94 {0, "NULL"},
95 {1, "LOAD"},
96 {2, "DYN"},
97 {3, "INTPR"},
98 {4, "NOTE"},
99 {5, "SHLIB"},
100 {6, "PHDR"},
101 {0, NULL}
104 static struct id2name_tbl t_compressed[] = {
105 {1, "[NO ]"},
106 {2, "[YES]"},
107 {0, NULL}
110 static struct id2name_tbl t_encrypted[] = {
111 {0, "[N/A]"},
112 {1, "[YES]"},
113 {2, "[NO ]"},
114 {0, NULL}
117 static void parse_self(void)
119 sdk_type = be16(self + 0x08);
120 meta_offset = be32(self + 0x0c);
121 header_len = be64(self + 0x10);
122 filesize = be64(self + 0x18);
123 info_offset = be64(self + 0x28);
124 elf_offset = be64(self + 0x30);
125 phdr_offset = be64(self + 0x38) - elf_offset;
126 shdr_offset = be64(self + 0x40) - elf_offset;
127 sec_offset = be64(self + 0x48);
128 ver_info = be64(self + 0x50);
129 ctrl_offset = be64(self + 0x58);
130 ctrl_size = be64(self + 0x60);
132 vendorid = be32(self + info_offset + 0x08);
133 authid = be64(self + info_offset + 0x00);
134 app_type = be32(self + info_offset + 0x0c);
135 app_version = be64(self + info_offset + 0x10);
137 elf = self + elf_offset;
138 arch64 = elf_read_hdr(elf, &ehdr);
142 static struct keylist *self_load_keys(void)
144 enum sce_key id;
146 switch (app_type) {
147 case 1:
148 id = KEY_LV0;
149 break;
150 case 2:
151 id = KEY_LV1;
152 break;
153 case 3:
154 id = KEY_LV2;
155 break;
156 case 4:
157 id = KEY_APP;
158 break;
159 case 5:
160 id = KEY_ISO;
161 break;
162 case 6:
163 id = KEY_LDR;
164 break;
165 case 8:
166 return NULL;
167 break;
168 default:
169 fail("invalid type: %08x", app_type);
172 return keys_get(id);
175 static void decrypt_header(void)
177 struct keylist *klist;
179 klist = self_load_keys();
180 if (klist == NULL)
181 return;
183 decrypted = sce_decrypt_header(self, klist);
184 free(klist->keys);
185 free(klist);
189 static const char *get_auth_type(void)
191 return "Unknown";
194 static void show_self_header(void)
196 printf("SELF header\n");
197 printf(" elf #1 offset: %08x_%08x\n", (u32)(elf_offset>>32), (u32)elf_offset);
198 printf(" header len: %08x_%08x\n", (u32)(header_len>>32), (u32)header_len);
199 printf(" meta offset: %08x_%08x\n", 0, meta_offset);
200 printf(" phdr offset: %08x_%08x\n", (u32)(phdr_offset>>32), (u32)phdr_offset);
201 printf(" shdr offset: %08x_%08x\n", (u32)(shdr_offset>>32), (u32)shdr_offset);
202 printf(" file size: %08x_%08x\n", (u32)(filesize>>32), (u32)filesize);
203 printf(" auth id: %08x_%08x (%s)\n", (u32)(authid>>32), (u32)authid, get_auth_type());
204 printf(" vendor id: %08x\n", vendorid);
205 printf(" info offset: %08x_%08x\n", (u32)(info_offset >> 32), (u32)info_offset);
206 printf(" sinfo offset: %08x_%08x\n", (u32)(sec_offset >> 32), (u32)sec_offset);
207 printf(" version offset: %08x_%08x\n", (u32)(ver_info >> 32), (u32)ver_info);
208 printf(" control info: %08x_%08x (%08x_%08x bytes)\n",
209 (u32)(ctrl_offset >> 32), (u32)ctrl_offset,
210 (u32)(ctrl_size >> 32), (u32)ctrl_size);
212 printf(" app version: %x.%x.%x\n", (u16)(app_version >> 48), (u16)(app_version >> 32), (u32)app_version);
213 printf(" SDK type: %s\n", id2name(sdk_type, t_sdk_type, "unknown"));
214 printf(" app type: %s\n", id2name(app_type, t_app_type, "unknown"));
217 printf("\n");
220 static void print_hash(u8 *ptr, u32 len)
222 while(len--)
223 printf(" %02x", *ptr++);
227 static void show_ctrl(void)
229 u32 i, j;
230 u32 type, length;
232 printf("Control info\n");
234 for (i = 0; i < ctrl_size; ) {
235 type = be32(self + ctrl_offset + i);
236 length = be32(self + ctrl_offset + i + 0x04);
237 switch (type) {
238 case 1:
239 if (length == 0x30) {
240 printf(" control flags:\n ");
241 print_hash(self + ctrl_offset + i + 0x10, 0x10);
242 printf("\n");
243 break;
245 case 2:
246 if (length == 0x40) {
247 printf(" file digest:\n ");
248 print_hash(self + ctrl_offset + i + 0x10, 0x14);
249 printf("\n ");
250 print_hash(self + ctrl_offset + i + 0x24, 0x14);
251 printf("\n");
252 break;
254 if (length == 0x30) {
255 printf(" file digest:\n ");
256 print_hash(self + ctrl_offset + i + 0x10, 0x14);
257 printf("\n");
258 break;
260 case 3:
261 if (length == 0x90) {
263 char id[0x31];
264 memset(id, 0, 0x31);
265 memcpy(id, self + ctrl_offset + i + 0x20, 0x30);
267 printf(" NPDRM info:\n");
268 printf(" magic: %08x\n", be32(self + ctrl_offset + i + 0x10));
269 printf(" unk0 : %08x\n", be32(self + ctrl_offset + i + 0x14));
270 printf(" unk1 : %08x\n", be32(self + ctrl_offset + i + 0x18));
271 printf(" unk2 : %08x\n", be32(self + ctrl_offset + i + 0x1c));
272 printf(" content_id: %s\n", id);
273 printf(" digest: ");
274 print_hash(self + ctrl_offset + i + 0x50, 0x10);
275 printf("\n invdigest: ");
276 print_hash(self + ctrl_offset + i + 0x60, 0x10);
277 printf("\n xordigest: ");
278 print_hash(self + ctrl_offset + i + 0x70, 0x10);
279 printf("\n");
280 break;
282 default:
283 printf(" unknown:\n");
284 for(j = 0; j < length; j++) {
285 if ((j % 16) == 0)
286 printf(" ");
287 printf(" %02x", be8(self + ctrl_offset + i + j));
288 if ((j % 16) == 15 || (j == length - 1))
289 printf("\n");
291 break;
293 i += length;
295 printf("\n");
298 static void show_sinfo(void)
300 u32 i;
301 u64 offset, size;
302 u32 compressed, encrypted;
303 u32 unk1, unk2;
305 printf("Section header\n");
307 printf(" offset size compressed unk1"
308 " unk2 encrypted\n");
310 for (i = 0; i < ehdr.e_phnum; i++) {
311 offset = be64(self + sec_offset + i*0x20 + 0x00);
312 size = be64(self + sec_offset + i*0x20 + 0x08);
313 compressed = be32(self + sec_offset + i*0x20 + 0x10);
314 unk1 = be32(self + sec_offset + i*0x20 + 0x14);
315 unk2 = be32(self + sec_offset + i*0x20 + 0x18);
316 encrypted = be32(self + sec_offset + i*0x20 + 0x1c);
317 printf(" %08x_%08x %08x_%08x %s %08x %08x %s\n",
318 (u32)(offset >> 32), (u32)offset,
319 (u32)(size >> 32), (u32)size,
320 id2name(compressed, t_compressed, "[???]"),
321 unk1, unk2,
322 id2name(encrypted, t_encrypted, "[???]")
326 printf("\n");
329 static void show_meta(void)
331 u32 meta_len;
332 u32 meta_n_hdr;
333 u32 meta_n_keys;
334 u32 i;
335 u64 offset, size;
336 u8 *tmp;
338 printf("Encrypted Metadata\n");
340 if (sdk_type == 0x8000) {
341 printf(" no encrypted metadata in fselfs.\n\n");
342 return;
345 if (decrypted < 0) {
346 printf(" unable to decrypt metadata\n\n");
347 return;
350 meta_len = be32(self + meta_offset + 0x60 + 0x4);
351 meta_n_hdr = be32(self + meta_offset + 0x60 + 0xc);
352 meta_n_keys = be32(self + meta_offset + 0x60 + 0x10);
354 printf(" Key: ");
355 print_hash(self + meta_offset + 0x20, 0x10);
356 printf("\n");
358 printf(" IV : ");
359 print_hash(self + meta_offset + 0x40, 0x10);
360 printf("\n");
362 printf(" Signature end %08x\n", meta_len);
363 printf(" Sections %d\n", meta_n_hdr);
364 printf(" Keys %d\n", meta_n_keys);
365 printf("\n");
367 printf(" Sections\n");
368 printf(" Offset Length Key IV SHA1\n");
369 for (i = 0; i < meta_n_hdr; i++) {
370 tmp = self + meta_offset + 0x80 + 0x30*i;
371 offset = be64(tmp);
372 size = be64(tmp + 8);
373 printf(" %08x_%08x %08x_%08x %03d %03d %03d\n",
374 (u32)(offset >> 32), (u32)offset, (u32)(size >> 32), (u32)size,
375 be32(tmp + 0x24), be32(tmp + 0x28), be32(tmp + 0x1c));
377 printf("\n");
379 printf(" Keys\n");
380 printf(" Idx Data\n");
381 tmp = self + meta_offset + 0x80 + 0x30*meta_n_hdr;
382 for (i = 0; i < meta_n_keys; i++) {
383 printf(" %03d ", i);
384 print_hash(tmp + i*0x10, 0x10);
385 printf("\n");
387 printf("\n");
389 printf("\n");
393 static void show_elf_header(void)
395 printf("ELF header\n");
397 printf(" type: %s\n", id2name(ehdr.e_type, t_elf_type, "unknown"));
398 printf(" machine: %s\n", id2name(ehdr.e_machine, t_elf_machine, "unknown"));
399 printf(" version: %d\n", ehdr.e_version);
401 if (arch64) {
402 printf(" phdr offset: %08x_%08x\n",
403 (u32)(ehdr.e_phoff>>32), (u32)ehdr.e_phoff);
404 printf(" shdr offset: %08x_%08x\n",
405 (u32)(ehdr.e_phoff>>32), (u32)ehdr.e_shoff);
406 printf(" entry: %08x_%08x\n",
407 (u32)(ehdr.e_entry>>32), (u32)ehdr.e_entry);
408 } else {
409 printf(" phdr offset: %08x\n",
410 (u32)ehdr.e_phoff);
411 printf(" shdr offset: %08x\n",
412 (u32)ehdr.e_shoff);
413 printf(" entry: %08x\n",
414 (u32)ehdr.e_entry);
417 printf(" flags: %08x\n", ehdr.e_flags);
418 printf(" header size: %08x\n", ehdr.e_ehsize);
419 printf(" program header size: %08x\n",
420 ehdr.e_phentsize);
421 printf(" program headers: %d\n", ehdr.e_phnum);
422 printf(" section header size: %08x\n",
423 ehdr.e_shentsize);
424 printf(" section headers: %d\n", ehdr.e_shnum);
425 printf(" section header string table index: %d\n", ehdr.e_shtrndx);
427 printf("\n");
430 static void get_flags(u32 flags, char *ptr)
432 memset(ptr, '-', 3);
433 ptr[3] = 0;
435 if (flags & 4)
436 ptr[0] = 'r';
437 if (flags & 2)
438 ptr[1] = 'w';
439 if (flags & 1)
440 ptr[2] = 'x';
443 static void show_phdr(unsigned int idx)
445 struct elf_phdr p;
446 char ppc[4], spe[4], rsx[4];
448 elf_read_phdr(arch64, elf + phdr_offset + (ehdr.e_phentsize * idx), &p);
450 get_flags(p.p_flags, ppc);
451 get_flags(p.p_flags >> 20, spe);
452 get_flags(p.p_flags >> 24, rsx);
454 if (arch64) {
455 printf(" %5s %08x_%08x %08x_%08x %08x_%08x\n"
456 " %08x_%08x %08x_%08x"
457 " %s %s %s %08x_%08x\n",
458 id2name(p.p_type, t_phdr_type, "?????"),
459 (u32)(p.p_off >> 32) , (u32)p.p_off,
460 (u32)(p.p_vaddr >> 32) , (u32)p.p_vaddr,
461 (u32)(p.p_paddr >> 32) , (u32)p.p_paddr,
462 (u32)(p.p_memsz >> 32) , (u32)p.p_memsz,
463 (u32)(p.p_filesz >> 32) , (u32)p.p_filesz,
464 ppc, spe, rsx,
465 (u32)(p.p_align >> 32) , (u32)p.p_align
467 } else {
468 printf(" %5s %08x %08x %08x "
469 "%08x %08x %s %s %s %08x\n",
470 id2name(p.p_type, t_phdr_type, "?????"),
471 (u32)p.p_off, (u32)p.p_vaddr,
472 (u32)p.p_paddr, (u32)p.p_memsz, (u32)p.p_filesz,
473 ppc, spe, rsx, (u32)p.p_align);
477 static void get_shdr_flags(u32 flags, char *ptr)
479 memset(ptr, ' ', 3);
480 ptr[3] = 0;
482 if (flags & 4)
483 ptr[0] = 'w';
484 if (flags & 2)
485 ptr[1] = 'a';
486 if (flags & 1)
487 ptr[2] = 'e';
490 static void show_shdr(unsigned int idx)
492 struct elf_shdr s;
493 char flags[4];
495 elf_read_shdr(arch64, elf + shdr_offset + (ehdr.e_shentsize * idx), &s);
496 get_shdr_flags(s.sh_flags, flags);
498 if (arch64) {
499 printf(" [%02d] %-15s %-9s %08x_%08x"
500 " %02d %-3s %02d %03d %02d\n"
501 " %08x_%08x %08x_%08x\n",
502 idx, "<no-name>",
503 id2name(s.sh_type, t_shdr_type, "????"),
504 (u32)(s.sh_addr >> 32), (u32)s.sh_addr,
505 s.sh_entsize, flags, s.sh_link, s.sh_info,
506 s.sh_addralign,
507 (u32)(s.sh_offset >> 32), (u32)s.sh_offset,
508 0, (u32)s.sh_size
510 } else {
511 printf(" [%02d] %-15s %-9s %08x"
512 " %08x %08x %02d %-3s %02d %02d %02d\n",
513 idx, "<no-name>",
514 id2name(s.sh_type, t_shdr_type, "????"),
515 (u32)s.sh_addr, (u32)s.sh_offset,
516 s.sh_size, s.sh_entsize,
517 flags, s.sh_link, s.sh_info, s.sh_addralign);
522 static void show_phdrs(void)
524 unsigned int i;
526 printf("Program headers\n");
528 if (ehdr.e_phnum == 0) {
529 printf("No program headers in this file.\n");
530 } else {
531 if (arch64)
532 printf(" type offset vaddr "
533 "paddr\n memsize filesize"
534 " PPU SPE RSX align\n");
535 else
536 printf(" type offset vaddr paddr "
537 "memsize filesize PPU SPE RSX align\n");
538 for (i = 0; i < ehdr.e_phnum; i++)
539 show_phdr(i);
542 printf("\n");
545 static void show_shdrs(void)
547 unsigned int i;
549 printf("Section headers\n");
551 if (ehdr.e_shnum == 0) {
552 printf("No section headers in this file.\n");
553 } else {
554 if (arch64)
555 printf(" [Nr] Name Type Addr"
556 " ES Flg Lk Inf Al\n"
557 " Off Size\n");
558 else
559 printf(" [Nr] Name Type Addr"
560 " Off Size ES Flg Lk Inf Al\n");
561 for (i = 0; i < ehdr.e_shnum; i++)
562 show_shdr(i);
565 printf("\n");
568 int main(int argc, char *argv[])
570 if (argc != 2)
571 fail("usage: readself file.self");
573 self = mmap_file(argv[1]);
575 parse_self();
576 decrypt_header();
578 show_self_header();
579 show_ctrl();
580 show_sinfo();
581 show_meta();
582 show_elf_header();
583 show_phdrs();
584 show_shdrs();
586 return 0;