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
13 #define MKDIR(x,y) mkdir(x)
15 #define MKDIR(x,y) mkdir(x,y)
18 static u8
*pup
= NULL
;
19 static u8 pup_hmac
[0x40];
20 static int got_hmac
= -1;
21 static u64 n_sections
;
24 static struct id2name_tbl t_names
[] = {
25 {0x100, "version.txt"},
26 {0x101, "license.xml"},
27 {0x102, "promo_flags.txt"},
28 {0x103, "update_flags.txt"},
29 {0x104, "patch_build.txt"},
30 {0x200, "ps3swu.self"},
33 {0x203, "patch_data.pkg"},
34 {0x300, "update_files.tar"},
35 {0x501, "spkg_hdr.tar"},
36 {0x601, "ps3swu2.self"},
40 static int check_hmac(u8
*hmac
, u8
*bfr
, u64 len
)
50 sha1_hmac(pup_hmac
, bfr
, len
, calc
);
52 if (memcmp(calc
, hmac
, sizeof calc
) == 0)
58 static u8
*find_hmac(u32 entry
)
63 ptr
= pup
+ 0x30 + 0x20 * n_sections
;
65 for(i
= 0; i
< n_sections
; i
++) {
66 if (be64(ptr
) == entry
)
71 fail("not found: %d", entry
);
75 static void do_section(u64 i
)
83 const char *hmac_status
;
85 ptr
= pup
+ 0x30 + 0x20 * i
;
87 offset
= be64(ptr
+ 0x08);
88 size
= be64(ptr
+ 0x10);
90 fname
= id2name(entry
, t_names
, NULL
);
92 fail("unknown entry id: %08x_%08x", (u32
)(entry
>> 32), (u32
)entry
);
94 hmac_res
= check_hmac(find_hmac(i
), pup
+ offset
, size
);
97 else if (hmac_res
== 0)
102 printf("unpacking %s (%08x_%08x bytes; hmac: %s)...\n", fname
, (u32
)(size
>> 32), (u32
)size
, hmac_status
);
103 memcpy_to_file(fname
, pup
+ offset
, size
);
106 static void do_pup(void)
112 n_sections
= be64(pup
+ 0x18);
113 hdr_size
= be64(pup
+ 0x20);
114 data_size
= be64(pup
+ 0x28);
116 printf("sections: %" PRIu64
"\n", n_sections
);
117 printf("hdr size: %08x_%08x\n", (u32
)(hdr_size
>> 32), (u32
)hdr_size
);
118 printf("data size: %08x_%08x\n", (u32
)(data_size
>> 32), (u32
)data_size
);
119 printf("header hmac: ");
121 res
= check_hmac(pup
+ 0x30 + 0x40 * n_sections
, pup
, 0x30 + 0x40 * n_sections
);
130 for (i
= 0; i
< n_sections
; i
++)
134 int main(int argc
, char *argv
[])
139 fail("usage: pupunpack filename.pup directory");
141 got_hmac
= key_get_simple("pup-hmac", pup_hmac
, sizeof pup_hmac
);
142 pup
= mmap_file(argv
[1]);
146 if (MKDIR(argv
[2], 0777) < 0)
147 fail("mkdir(%s)", argv
[2]);
148 if (chdir(argv
[2]) < 0)
149 fail("chdir(%s)", argv
[2]);