]> git.sesse.net Git - pistorm/blob - platforms/amiga/hunk-reloc.c
Some PiSCSI file system reloc changes
[pistorm] / platforms / amiga / hunk-reloc.c
1 // SPDX-License-Identifier: MIT
2
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <endian.h>
9 #include "hunk-reloc.h"
10 #include "piscsi/piscsi-enums.h"
11 #include "piscsi/piscsi.h"
12
13 #ifdef FAKESTORM
14 #define lseek64 lseek
15 #endif
16
17 #define DEBUG_SPAMMY(...)
18 //#define DEBUG_SPAMMY printf
19 #define DEBUG(...)
20 //#define DEBUG printf
21
22 #define BE(val) be32toh(val)
23 #define BE16(val) be16toh(val)
24
25 #define READLW(a, b) fread(&a, 4, 1, b); a = be32toh(a);
26 #define READW(a, b) fread(&a, 2, 1, b); a = be16toh(a);
27
28 uint32_t lw = 0;
29 static uint32_t file_offset = 0, add_size = 0;
30
31 char *hunk_id_name(uint32_t index) {
32     switch (index) {
33         case HUNKTYPE_HEADER:
34             return "HUNK_HEADER";
35         case HUNKTYPE_CODE:
36             return "HUNK_CODE";
37         case HUNKTYPE_HUNK_RELOC32:
38             return "HUNK_RELOC32";
39         case HUNKTYPE_SYMBOL:
40             return "HUNK_SYMBOL";
41         case HUNKTYPE_BSS:
42             return "HUNK_BSS";
43         case HUNKTYPE_DATA:
44             return "HUNK_DATA";
45         case HUNKTYPE_END:
46             return "HUNK_END";
47         default:
48             return "UNKNOWN HUNK TYPE";
49     }
50 }
51
52 int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_reloc *r) {
53     if (!f)
54         return -1;
55     
56     uint32_t discard = 0, cur_hunk = 0, offs32 = 0;
57     
58     switch (index) {
59         case HUNKTYPE_HEADER:
60             DEBUG("[HUNK_RELOC] Processing hunk HEADER.\n");
61             do {
62                 READLW(discard, f);
63                 if (discard) {
64                     if (info->libnames[info->num_libs]) {
65                         free(info->libnames[info->num_libs]);
66                         info->libnames[info->num_libs] = NULL;
67                     }
68                     info->libnames[info->num_libs] = malloc(discard * 4);
69                     fread(info->libnames[info->num_libs], discard, 4, f);
70                     info->num_libs++;
71                 }
72             } while (discard);
73             
74             READLW(info->table_size, f);
75             DEBUG("[HUNK_RELOC] [HEADER] Table size: %d\n", info->table_size);
76             READLW(info->first_hunk, f);
77             READLW(info->last_hunk, f);
78             info->num_hunks = (info->last_hunk - info->first_hunk) + 1;
79             DEBUG("[HUNK_RELOC] [HEADER] First: %d Last: %d Num: %d\n", info->first_hunk, info->last_hunk, info->num_hunks);
80             if (info->hunk_sizes) {
81                 free(info->hunk_sizes);
82                 info->hunk_sizes = NULL;
83             }
84             if (info->hunk_offsets) {
85                 free(info->hunk_offsets);
86                 info->hunk_offsets = NULL;
87             }
88             info->hunk_sizes = malloc(info->num_hunks * 4);
89             info->hunk_offsets = malloc(info->num_hunks * 4);
90             for (uint32_t i = 0; i < info->table_size; i++) {
91                 READLW(info->hunk_sizes[i], f);
92                 DEBUG("[HUNK_RELOC] [HEADER] Hunk %d: %d (%.8X)\n", i, info->hunk_sizes[i] * 4, info->hunk_sizes[i] * 4);
93             }
94             info->header_size = (uint32_t)ftell(f) - file_offset;
95             DEBUG("[HUNK_RELOC] [HEADER] ~~~~~~~~~~~ Hunk HEADER size is %d ~~~~~~~~~~~~.\n", info->header_size);
96             return 0;
97             break;
98         case HUNKTYPE_CODE:
99             DEBUG("[HUNK_RELOC] Hunk %d: CODE.\n", info->current_hunk);
100             READLW(discard, f);
101             info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
102             DEBUG("[HUNK_RELOC] [CODE] Code hunk size: %d (%.8X)\n", discard * 4, discard * 4);
103             fseek(f, discard * 4, SEEK_CUR);
104             return 0;
105             break;
106         case HUNKTYPE_HUNK_RELOC32:
107             DEBUG("[HUNK_RELOC] Hunk %d: RELOC32.\n", info->current_hunk);
108             DEBUG("Processing Reloc32 hunk.\n");
109             do {
110                 READLW(discard, f);
111                 if (discard && discard != 0xFFFFFFFF) {
112                     READLW(cur_hunk, f);
113                     DEBUG("[HUNK_RELOC] [RELOC32] Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
114                     for(uint32_t i = 0; i < discard; i++) {
115                         READLW(offs32, f);
116                         DEBUG_SPAMMY("[HUNK_RELOC] [RELOC32] #%d: @%.8X in hunk %d\n", i + 1, offs32, cur_hunk);
117                         r[info->reloc_hunks].offset = offs32;
118                         r[info->reloc_hunks].src_hunk = info->current_hunk;
119                         r[info->reloc_hunks].target_hunk = cur_hunk;
120                         info->reloc_hunks++;
121                     }
122                 }
123             } while(discard);
124             return 0;
125             break;
126         case HUNKTYPE_SYMBOL:
127             DEBUG("[HUNK_RELOC] Hunk %d: SYMBOL.\n", info->current_hunk);
128             DEBUG("[HUNK_RELOC] [SYMBOL] Processing Symbol hunk.\n");
129             READLW(discard, f);
130             do {
131                 if (discard) {
132                     char sstr[256];
133                     memset(sstr, 0x00, 256);
134                     fread(sstr, discard, 4, f);
135                     READLW(discard, f);
136                     DEBUG("[HUNK_RELOC] [SYMBOL] Symbol: %s - %.8X\n", sstr, discard);
137                 }
138                 READLW(discard, f);
139             } while (discard);
140             return 0;
141             break;
142         case HUNKTYPE_BSS:
143             DEBUG("[HUNK_RELOC] Hunk %d: BSS.\n", info->current_hunk);
144             READLW(discard, f);
145             info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
146             DEBUG("[HUNK_RELOC] [BSS] Skipping BSS hunk. Size: %d\n", discard * 4);
147             add_size += (discard * 4);
148             return 0;
149         case HUNKTYPE_DATA:
150             DEBUG("[HUNK_RELOC] Hunk %d: DATA.\n", info->current_hunk);
151             READLW(discard, f);
152             info->hunk_offsets[info->current_hunk] = ftell(f) - file_offset;
153             DEBUG("[HUNK_RELOC] [DATA] Skipping data hunk. Size: %d.\n", discard * 4);
154             fseek(f, discard * 4, SEEK_CUR);
155             return 0;
156             break;
157         case HUNKTYPE_END:
158             DEBUG("[HUNK_RELOC] END: Ending hunk %d.\n", info->current_hunk);
159             info->current_hunk++;
160             return 0;
161             break;
162         default:
163             DEBUG("[!!!HUNK_RELOC] Unknown hunk type %.8X! Can't process!\n", index);
164             break;
165     }
166
167     return -1;
168 }
169
170 void reloc_hunk(struct hunk_reloc *h, uint8_t *buf, struct hunk_info *i) {
171     uint32_t rel = i->hunk_offsets[h->target_hunk];
172     uint32_t *src_ptr = (uint32_t *)(&buf[i->hunk_offsets[h->src_hunk] + h->offset]);
173
174     uint32_t src = be32toh(*src_ptr);
175     uint32_t dst = src + i->base_offset + rel;
176     DEBUG_SPAMMY("[HUNK-RELOC] %.8X -> %.8X\n", src, dst);
177     *src_ptr = htobe32(dst);
178 }
179
180 void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset) {
181     READLW(lw, in);
182     DEBUG_SPAMMY("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
183
184     file_offset = offset;
185     add_size = 0;
186
187     while (!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
188         READLW(lw, in);
189         if (feof(in)) goto end_parse;
190         DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
191         DEBUG("File pos: %.8lX\n", ftell(in) - file_offset);
192     }
193     end_parse:;
194     DEBUG("Done processing hunks.\n");
195 }
196
197 void reloc_hunks(struct hunk_reloc *r, uint8_t *buf, struct hunk_info *h_info) {
198     DEBUG("[HUNK-RELOC] Relocating %d offsets.\n", h_info->reloc_hunks);
199     for (uint32_t i = 0; i < h_info->reloc_hunks; i++) {
200         DEBUG_SPAMMY("[HUNK-RELOC] Relocating offset %d.\n", i);
201         reloc_hunk(&r[i], buf, h_info);
202     }
203     DEBUG("[HUNK-RELOC] Done relocating offsets.\n");
204 }
205
206 struct LoadSegBlock {
207     uint32_t   lsb_ID;
208     uint32_t   lsb_SummedLongs;
209     int32_t    lsb_ChkSum;
210     uint32_t   lsb_HostID;
211     uint32_t   lsb_Next;
212     uint32_t   lsb_LoadData[PISCSI_MAX_BLOCK_SIZE / 4];
213 };
214 #define LOADSEG_IDENTIFIER 0x4C534547
215
216 int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs, uint32_t block_size) {
217     if (fd == -1)
218         return -1;
219     
220     if (block_size == 0)
221         block_size = 512;
222
223     uint8_t *block = malloc(block_size);
224     uint32_t next_blk = 0;
225     struct LoadSegBlock *lsb = (struct LoadSegBlock *)block;
226
227     read(fd, block, block_size);
228     if (BE(lsb->lsb_ID) != LOADSEG_IDENTIFIER) {
229         DEBUG("[LOAD_LSEG] Attempted to load a non LSEG-block: %.8X", BE(lsb->lsb_ID));
230         goto fail;
231     }
232
233     char *filename = "data/lsegout.bin";
234     FILE *out = fopen(filename, "wb+");
235
236     DEBUG("[LOAD_LSEG] LSEG data:\n");
237     DEBUG("[LOAD_LSEG] Longs: %d HostID: %d\n", BE(lsb->lsb_SummedLongs), BE(lsb->lsb_HostID));
238     DEBUG("[LOAD_LSEG] Next: %d LoadData: %p\n", BE(lsb->lsb_Next), (void *)lsb->lsb_LoadData);
239     next_blk = BE(lsb->lsb_Next);
240     do {
241         next_blk = BE(lsb->lsb_Next);
242         fwrite(lsb->lsb_LoadData, 1, block_size - 20, out);
243         lseek64(fd, next_blk * block_size, SEEK_SET);
244         read(fd, block, block_size);
245     } while (next_blk != 0xFFFFFFFF);
246     
247     uint32_t file_size = ftell(out);
248     fseek(out, 0, SEEK_SET);
249     uint8_t *buf = malloc(file_size + 1024);
250     fread(buf, file_size, 1, out);
251     fseek(out, 0, SEEK_SET);
252     process_hunks(out, i, relocs, 0x0);
253
254     fclose(out);
255     *buf_p = buf;
256     i->byte_size = file_size;
257     i->alloc_size = file_size + add_size;
258
259     return 0;
260
261 fail:;
262     if (block)
263         free(block);
264
265     return -1;
266 }
267
268 int load_fs(struct piscsi_fs *fs, char *dosID) {
269     char filename[256];
270     memset(filename, 0x00, 256);
271     sprintf(filename, "./data/fs/%c%c%c.%d", dosID[0], dosID[1], dosID[2], dosID[3]);
272
273     FILE *in = fopen(filename, "rb");
274     if (in == NULL)
275         return -1;
276
277     fseek(in, 0, SEEK_END);
278     uint32_t file_size = ftell(in);
279     fseek(in, 0, SEEK_SET);
280
281     fs->binary_data = malloc(file_size);
282     fread(fs->binary_data, file_size, 1, in);
283     fseek(in, 0, SEEK_SET);
284     process_hunks(in, &fs->h_info, fs->relocs, 0x0);
285     fs->h_info.byte_size = file_size;
286     fs->h_info.alloc_size = file_size + add_size;
287
288     fclose(in);
289
290     return 0;
291 }