12 static const u8
*super
;
18 static const u8
*map_rom(const char *name
)
20 int fd
= open(name
, O_RDONLY
);
21 void *map
= mmap(0, 0x20000000, PROT_READ
, MAP_SHARED
, fd
, 0);
26 static const u8
*find_super(void)
29 const u8
*super
= 0, *p
;
31 for (p
= rom
+ 0x1fc00000; p
< rom
+ 0x20000000; p
+= 0x40000)
32 if (be32(p
) == 0x53464653) {
33 u32 version
= be32(p
+ 4);
34 if (super
== 0 || version
> newest
) {
43 static void print_mode(u8 mode
)
46 const char dir
[4] = "?-d?";
47 const char perm
[3] = "-rw";
49 fprintf(stderr
, "%c", dir
[mode
& 3]);
50 for (i
= 0; i
< 3; i
++) {
51 fprintf(stderr
, "%c", perm
[(mode
>> 6) & 1]);
52 fprintf(stderr
, "%c", perm
[(mode
>> 6) & 2]);
57 static void print_entry(const u8
*entry
)
66 memcpy(name
, entry
, 12);
70 sub
= be16(entry
+ 0x0e);
71 sib
= be16(entry
+ 0x10);
72 size
= be32(entry
+ 0x12);
73 x1
= be16(entry
+ 0x16);
74 uid
= be16(entry
+ 0x18);
75 gid
= be16(entry
+ 0x1a);
76 x3
= be32(entry
+ 0x1c);
79 fprintf(stderr
, " %02x %04x %04x %08x (%04x %08x) %s\n",
80 attr
, uid
, gid
, size
, x1
, x3
, name
);
83 static u8 block
[0x4000];
85 static void do_file(const u8
*entry
, const char *parent_path
)
94 memcpy(name
, entry
, 12);
96 sub
= be16(entry
+ 0x0e);
97 size
= be32(entry
+ 0x12);
99 if (parent_path
[strlen(parent_path
) - 1] == '/' || name
[0] == '/')
100 sprintf(path
, "%s%s", parent_path
, name
);
102 sprintf(path
, "%s/%s", parent_path
, name
);
104 fp
= fopen(path
+ 1, "wb");
107 this_size
= size
> 0x4000 ? 0x4000 : size
;
109 memset(iv
, 0, sizeof iv
);
110 aes_cbc_dec(key
, iv
, (u8
*)rom
+ 0x4000*sub
, 0x4000, block
);
112 fwrite(block
, 1, this_size
, fp
);
115 sub
= be16(fat
+ 2*sub
);
121 static void do_entry(const u8
*entry
, const char *parent_path
);
123 static void print_dir_entries(const u8
*entry
)
127 sib
= be16(entry
+ 0x10);
130 print_dir_entries(fst
+ 0x20*sib
);
135 static void do_dir(const u8
*entry
, const char *parent_path
)
141 memcpy(name
, entry
, 12);
143 sub
= be16(entry
+ 0x0e);
144 sib
= be16(entry
+ 0x10);
146 if (parent_path
[strlen(parent_path
) - 1] == '/' || name
[0] == '/')
147 sprintf(path
, "%s%s", parent_path
, name
);
149 sprintf(path
, "%s/%s", parent_path
, name
);
150 fprintf(stderr
, "%s:\n", path
);
152 print_dir_entries(fst
+ 0x20*sub
);
153 fprintf(stderr
, "\n");
156 mkdir(path
+ 1, 0777);
159 do_entry(fst
+ 0x20*sub
, path
);
162 static void do_entry(const u8
*entry
, const char *parent_path
)
168 sib
= be16(entry
+ 0x10);
171 do_entry(fst
+ 0x20*sib
, parent_path
);
177 do_file(entry
, parent_path
);
180 do_dir(entry
, parent_path
);
183 fprintf(stderr
, "unknown mode! (%d)\n", mode
);
187 int main(int argc
, char **argv
)
189 get_key("default/nand-key", key
, 16);
191 rom
= map_rom(argv
[1]);
192 super
= find_super();
196 mkdir(argv
[2], 0777);