-
Notifications
You must be signed in to change notification settings - Fork 24
/
puppack.c
146 lines (116 loc) · 2.85 KB
/
puppack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2010 Sven Peter <[email protected]>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "tools.h"
#define MAX_FILES 10
static FILE *fp;
static u8 pup_hmac[0x40];
static u8 hdr[0x30 + 0x40 * MAX_FILES + 0x20];
static u64 n_files;
static u64 data_size;
static u64 build = 0xfa11;
static struct {
u8 *ptr;
u64 id;
u64 len;
u64 offset;
} files[MAX_FILES];
static struct id2name_tbl t_names[] = {
{0x100, "version.txt"},
{0x101, "license.txt"},
{0x102, "promo_flags.txt"},
{0x103, "update_flags.txt"},
{0x104, "patch_build.txt"},
{0x200, "ps3swu.self"},
{0x201, "vsh.tar"},
{0x202, "dots.txt"},
{0x203, "patch_data.pkg"},
{0x300, "update_files.tar"},
{0, NULL}
};
static void find_files(void)
{
struct id2name_tbl *t;
struct stat st;
u64 offset;
u32 i;
n_files = 0;
data_size = 0;
t = t_names;
while(t->name != NULL) {
if (stat(t->name, &st) >= 0) {
files[n_files].id = t->id;
files[n_files].ptr = mmap_file(t->name);
files[n_files].len = st.st_size;
data_size += files[n_files].len;
n_files++;
}
t++;
}
offset = 0x50 + 0x40 * n_files;
for (i = 0; i < n_files; i++) {
files[i].offset = offset;
offset += files[i].len;
}
}
static void calc_hmac(u8 *ptr, u64 len, u8 *hmac)
{
memset(hmac, 0, 0x20);
sha1_hmac(pup_hmac, ptr, len, hmac);
}
static void build_header(void)
{
u32 i;
memset(hdr, 0, sizeof hdr);
memcpy(hdr, "SCEUF\0\0\0", 8);
wbe64(hdr + 0x08, 1);
wbe64(hdr + 0x10, build);
wbe64(hdr + 0x18, n_files);
wbe64(hdr + 0x20, 0x50 + n_files * 0x40);
wbe64(hdr + 0x28, data_size);
for (i = 0; i < n_files; i++) {
wbe64(hdr + 0x30 + 0x20 * i + 0x00, files[i].id);
wbe64(hdr + 0x30 + 0x20 * i + 0x08, files[i].offset);
wbe64(hdr + 0x30 + 0x20 * i + 0x10, files[i].len);
wbe64(hdr + 0x30 + 0x20 * i + 0x18, 0);
wbe64(hdr + 0x30 + 0x20 * n_files + 0x20 * i, i);
calc_hmac(files[i].ptr, files[i].len,
hdr + 0x30 + 0x20 * n_files + 0x20 * i + 0x08);
}
calc_hmac(hdr, 0x30 + 0x40 * n_files,
hdr + 0x30 + 0x40 * n_files);
}
static void write_pup(void)
{
u32 i;
fseek(fp, 0, SEEK_SET);
fwrite(hdr, 0x50 + 0x40 * n_files, 1, fp);
for (i = 0; i < n_files; i++) {
fseek(fp, files[i].offset, SEEK_SET);
fwrite(files[i].ptr, files[i].len, 1, fp);
}
}
int main(int argc, char *argv[])
{
if (argc < 3)
fail("usage: puppack filename.pup directory [build number]");
if (argc == 4)
build = atoi(argv[3]);
if (key_get_simple("pup-hmac", pup_hmac, sizeof pup_hmac) < 0)
fail("pup hmac key not available");
fp = fopen(argv[1], "wb");
if (fp == NULL)
fail("fopen(%s)", argv[1]);
if (chdir(argv[2]) < 0)
fail("chdir(%s)", argv[1]);
find_files();
build_header();
write_pup();
fclose(fp);
return 0;
}