]> git.sesse.net Git - pistorm/blob - platforms/amiga/hunk-reloc.c
Some non-working loading of file systems from disk for PiSCSI
[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(...)
18 //#define DEBUG printf
19
20 #define BE(val) be32toh(val)
21 #define BE16(val) be16toh(val)
22
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);
25
26 uint32_t lw = 0;
27 static uint32_t file_offset = 0, add_size = 0;
28
29 char *hunk_id_name(uint32_t index) {
30     switch (index) {
31         case HUNKTYPE_HEADER:
32             return "HUNK_HEADER";
33         case HUNKTYPE_CODE:
34             return "HUNK_CODE";
35         case HUNKTYPE_HUNK_RELOC32:
36             return "HUNK_RELOC32";
37         case HUNKTYPE_SYMBOL:
38             return "HUNK_SYMBOL";
39         case HUNKTYPE_BSS:
40             return "HUNK_BSS";
41         case HUNKTYPE_DATA:
42             return "HUNK_DATA";
43         case HUNKTYPE_END:
44             return "HUNK_END";
45         default:
46             return "UNKNOWN HUNK TYPE";
47     }
48 }
49
50 int process_hunk(uint32_t index, struct hunk_info *info, FILE *f, struct hunk_reloc *r) {
51     if (!f)
52         return -1;
53     
54     uint32_t discard = 0, cur_hunk = 0, offs32 = 0;
55     
56     switch (index) {
57         case HUNKTYPE_HEADER:
58             DEBUG("Processing hunk header.\n");
59             do {
60                 READLW(discard, f);
61                 if (discard) {
62                     info->libnames[info->num_libs] = malloc(discard * 4);
63                     fread(info->libnames[info->num_libs], discard, 4, f);
64                     info->num_libs++;
65                 }
66             } while (discard);
67             
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);
79             }
80             return 0;
81             break;
82         case HUNKTYPE_CODE:
83             DEBUG("Hunk %d: CODE.\n", info->current_hunk);
84             READLW(discard, f);
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);
88             return 0;
89             break;
90         case HUNKTYPE_HUNK_RELOC32:
91             DEBUG("Hunk %d: RELOC32.\n", info->current_hunk);
92             DEBUG("Processing Reloc32 hunk.\n");
93             do {
94                 READLW(discard, f);
95                 if (discard && discard != 0xFFFFFFFF) {
96                     READLW(cur_hunk, f);
97                     DEBUG("Relocating %d offsets pointing to hunk %d.\n", discard, cur_hunk);
98                     for(uint32_t i = 0; i < discard; i++) {
99                         READLW(offs32, f);
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;
104                         info->reloc_hunks++;
105                     }
106                 }
107             } while(discard);
108             return 0;
109             break;
110         case HUNKTYPE_SYMBOL:
111             DEBUG("Hunk %d: SYMBOL.\n", info->current_hunk);
112             DEBUG("Processing Symbol hunk.\n");
113             READLW(discard, f);
114             do {
115                 if (discard) {
116                     char sstr[256];
117                     memset(sstr, 0x00, 256);
118                     fread(sstr, discard, 4, f);
119                     READLW(discard, f);
120                     DEBUG("Symbol: %s - %.8X\n", sstr, discard);
121                 }
122                 READLW(discard, f);
123             } while (discard);
124             return 0;
125             break;
126         case HUNKTYPE_BSS:
127             DEBUG("Hunk %d: BSS.\n", info->current_hunk);
128             READLW(discard, f);
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);
132             return 0;
133         case HUNKTYPE_DATA:
134             DEBUG("Hunk %d: DATA.\n", info->current_hunk);
135             READLW(discard, f);
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);
139             return 0;
140             break;
141         case HUNKTYPE_END:
142             DEBUG("END: Ending hunk %d.\n", info->current_hunk);
143             info->current_hunk++;
144             return 0;
145             break;
146         default:
147             DEBUG("Unknown hunk type %.8X! Can't process!\n", index);
148             break;
149     }
150
151     return -1;
152 }
153
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]);
157
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);
162 }
163
164 void process_hunks(FILE *in, struct hunk_info *h_info, struct hunk_reloc *r, uint32_t offset) {
165     READLW(lw, in);
166     DEBUG("Hunk ID: %.8X (%s)\n", lw, hunk_id_name(lw));
167
168     file_offset = offset;
169     add_size = 0;
170
171     while (!feof(in) && process_hunk(lw, h_info, in, r) != -1) {
172         READLW(lw, in);
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);
176     }
177     end_parse:;
178     DEBUG("Done processing hunks.\n");
179 }
180
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);
186     }
187     DEBUG("Done relocating offsets.\n");
188 }
189
190 struct LoadSegBlock {
191     uint32_t   lsb_ID;
192     uint32_t   lsb_SummedLongs;
193     int32_t    lsb_ChkSum;
194     uint32_t   lsb_HostID;
195     uint32_t   lsb_Next;
196     uint32_t   lsb_LoadData[PISCSI_MAX_BLOCK_SIZE / 4];
197 };
198 #define LOADSEG_IDENTIFIER 0x4C534547
199
200 int load_lseg(int fd, uint8_t **buf_p, struct hunk_info *i, struct hunk_reloc *relocs, uint32_t block_size) {
201     if (fd == -1)
202         return -1;
203     
204     if (block_size == 0)
205         block_size = 512;
206
207     uint8_t *block = malloc(block_size);
208     uint32_t next_blk = 0;
209     struct LoadSegBlock *lsb = (struct LoadSegBlock *)block;
210
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));
214         goto fail;
215     }
216
217     char *filename = "data/lsegout.bin";
218     FILE *out = fopen(filename, "wb+");
219
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);
224     do {
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);
230     
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);
237
238     fclose(out);
239     *buf_p = buf;
240     i->byte_size = file_size;
241     i->alloc_size = file_size + add_size;
242
243     return 0;
244
245 fail:;
246     if (block)
247         free(block);
248
249     return -1;
250 }
251
252 int load_fs(struct piscsi_fs *fs, char *dosID) {
253     char filename[256];
254     memset(filename, 0x00, 256);
255     sprintf(filename, "./data/fs/%c%c%c.%d", dosID[0], dosID[1], dosID[2], dosID[3]);
256
257     FILE *in = fopen(filename, "rb");
258     if (in == NULL)
259         return -1;
260
261     fseek(in, 0, SEEK_END);
262     uint32_t file_size = ftell(in);
263     fseek(in, 0, SEEK_SET);
264
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;
270
271     fclose(in);
272
273     return 0;
274 }