1 // SPDX-License-Identifier: MIT
9 #include "hunk-reloc.h"
10 #include "piscsi/piscsi-enums.h"
11 #include "piscsi/piscsi.h"
18 //#define DEBUG printf
20 #define BE(val) be32toh(val)
21 #define BE16(val) be16toh(val)
23 #define READLW(a, b) fread(&a, 4, 1, b); a = be32toh(a);
24 #define READW(a, b) fread(&a, 2, 1, b); a = be16toh(a);
27 static uint32_t file_offset = 0, add_size = 0;
29 char *hunk_id_name(uint32_t index) {
35 case HUNKTYPE_HUNK_RELOC32:
36 return "HUNK_RELOC32";
46 return "UNKNOWN HUNK TYPE";
50 int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_reloc *r) {
54 uint32_t discard = 0, cur_hunk = 0, offs32 = 0;
58 DEBUG("Processing hunk header.\n");
62 info->libnames[info->num_libs] = malloc(discard * 4);
63 fread(info->libnames[info->num_libs], discard, 4, f);
68 READLW(info->table_size, f);
69 DEBUG("Table size: %d\n", info->table_size);
70 READLW(info->first_hunk, f);
71 READLW(info->last_hunk, f);
72 info->num_hunks = (info->last_hunk - info->first_hunk) + 1;
73 DEBUG("First: %d Last: %d Num: %d\n", info->first_hunk, info->last_hunk, info->num_hunks);
74 info->hunk_sizes = malloc(info->num_hunks * 4);
75 info->hunk_offsets = malloc(info->num_hunks * 4);
76 for (uint32_t i = 0; i < info->table_size; i++) {
77 READLW(info->hunk_sizes[i], f);
78 DEBUG("Hunk %d: %d (%.8X)\n", i, info->hunk_sizes[i] * 4, info->hunk_sizes[i] * 4);
83 DEBUG("Hunk %d: CODE.\n", info->current_hunk);
85 info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
86 DEBUG("Code hunk size: %d (%.8X)\n", discard * 4, discard * 4);
87 fseek(f, discard * 4, SEEK_CUR);
90 case HUNKTYPE_HUNK_RELOC32:
91 DEBUG("Hunk %d: RELOC32.\n", info->current_hunk);
92 DEBUG("Processing Reloc32 hunk.\n");
95 if (discard && discard != 0xFFFFFFFF) {
97 DEBUG("Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
98 for(uint32_t i = 0; i < discard; i++) {
100 DEBUG("#%d: @%.8X in hunk %d\n", i + 1, offs32, cur_hunk);
101 r[info->reloc_hunks].offset = offs32;
102 r[info->reloc_hunks].src_hunk = info->current_hunk;
103 r[info->reloc_hunks].target_hunk = cur_hunk;
110 case HUNKTYPE_SYMBOL:
111 DEBUG("Hunk %d: SYMBOL.\n", info->current_hunk);
112 DEBUG("Processing Symbol hunk.\n");
117 memset(sstr, 0x00, 256);
118 fread(sstr, discard, 4, f);
120 DEBUG("Symbol: %s - %.8X\n", sstr, discard);
127 DEBUG("Hunk %d: BSS.\n", info->current_hunk);
129 info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
130 DEBUG("Skipping BSS hunk. Size: %d\n", discard * 4);
131 add_size += (discard * 4);
134 DEBUG("Hunk %d: DATA.\n", info->current_hunk);
136 info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
137 DEBUG("Skipping data hunk. Size: %d.\n", discard * 4);
138 fseek(f, discard * 4, SEEK_CUR);
142 DEBUG("END: Ending hunk %d.\n", info->current_hunk);
143 info->current_hunk++;
147 DEBUG("Unknown hunk type %.8X! Can't process!\n", index);
154 void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i) {
155 uint32_t rel = i->hunk_offsets[h->target_hunk];
156 uint32_t *src_ptr = (uint32_t *)(&buf[i->hunk_offsets[h->src_hunk] + h->offset]);
158 uint32_t src = be32toh(*src_ptr);
159 uint32_t dst = src + i->base_offset + rel;
160 DEBUG("%.8X -> %.8X\n", src, dst);
161 *src_ptr = htobe32(dst);
164 void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset) {
166 DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
168 file_offset = offset;
171 while (!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
173 if (feof(in)) goto end_parse;
174 DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
175 DEBUG("File pos: %.8lX\n", ftell(in) - file_offset);
178 DEBUG("Done processing hunks.\n");
181 void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info) {
182 DEBUG("Relocating %d offsets.\n", h_info->reloc_hunks);
183 for (uint32_t i = 0; i < h_info->reloc_hunks; i++) {
184 DEBUG("Relocating offset %d.\n", i);
185 reloc_hunk(&r[i], buf, h_info);
187 DEBUG("Done relocating offsets.\n");
190 struct LoadSegBlock {
192 uint32_t lsb_SummedLongs;
196 uint32_t lsb_LoadData[PISCSI_MAX_BLOCK_SIZE / 4];
198 #define LOADSEG_IDENTIFIER 0x4C534547
200 int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs, uint32_t block_size) {
207 uint8_t *block = malloc(block_size);
208 uint32_t next_blk = 0;
209 struct LoadSegBlock *lsb = (struct LoadSegBlock *)block;
211 read(fd, block, block_size);
212 if (BE(lsb->lsb_ID) != LOADSEG_IDENTIFIER) {
213 DEBUG("[LOAD_LSEG] Attempted to load a non LSEG-block: %.8X", BE(lsb->lsb_ID));
217 char *filename = "data/lsegout.bin";
218 FILE *out = fopen(filename, "wb+");
220 DEBUG("[LOAD_LSEG] LSEG data:\n");
221 DEBUG("[LOAD_LSEG] Longs: %d HostID: %d\n", BE(lsb->lsb_SummedLongs), BE(lsb->lsb_HostID));
222 DEBUG("[LOAD_LSEG] Next: %d LoadData: %p\n", BE(lsb->lsb_Next), (void *)lsb->lsb_LoadData);
223 next_blk = BE(lsb->lsb_Next);
225 next_blk = BE(lsb->lsb_Next);
226 fwrite(lsb->lsb_LoadData, 1, block_size - 20, out);
227 lseek64(fd, next_blk * block_size, SEEK_SET);
228 read(fd, block, block_size);
229 } while (next_blk != 0xFFFFFFFF);
231 uint32_t file_size = ftell(out);
232 fseek(out, 0, SEEK_SET);
233 uint8_t *buf = malloc(file_size + 1024);
234 fread(buf, file_size, 1, out);
235 fseek(out, 0, SEEK_SET);
236 process_hunks(out, i, relocs, 0x0);
240 i->byte_size = file_size;
241 i->alloc_size = file_size + add_size;
252 int load_fs(struct piscsi_fs *fs, char *dosID) {
254 memset(filename, 0x00, 256);
255 sprintf(filename, "./data/fs/%c%c%c.%d", dosID[0], dosID[1], dosID[2], dosID[3]);
257 FILE *in = fopen(filename, "rb");
261 fseek(in, 0, SEEK_END);
262 uint32_t file_size = ftell(in);
263 fseek(in, 0, SEEK_SET);
265 fs->binary_data = malloc(file_size);
266 fread(fs->binary_data, file_size, 1, in);
267 process_hunks(in, &fs->h_info, fs->relocs, 0x0);
268 fs->h_info.byte_size = file_size;
269 fs->h_info.alloc_size = file_size + add_size;