Forward compatibility: build relative-base link libraries where needed
[AROS.git] / arch / ppc-sam440 / boot / parthenope / tools / parthenope-install.c
blob52e09af30fa3fef9aef2b0a5a3e6d0fb31c4de51
1 /* parthenope-install.c */
3 /* <project_name> -- <project_description>
5 * Copyright (C) 2006 - 2007
6 * Giuseppe Coviello <cjg@cruxppc.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
30 #include "../src/rdb.h"
32 static int checksum(struct AmigaBlock *_header)
34 struct AmigaBlock *header;
35 header = malloc(512);
36 memmove(header, _header, 512);
37 int32_t *block = (int32_t *) header;
38 uint32_t i;
39 int32_t sum = 0;
40 if (header->amiga_SummedLongss > 512)
41 header->amiga_SummedLongss = 512;
42 for (i = 0; i < header->amiga_SummedLongss; i++)
43 sum += *block++;
44 free(header);
45 return sum;
48 static inline void calculate_checksum(struct AmigaBlock *blk)
50 blk->amiga_ChkSum = blk->amiga_ChkSum - checksum(blk);
51 return;
54 static struct AmigaBlock *read_block(FILE * dev,
55 struct AmigaBlock *blk, uint32_t block)
57 uint32_t pos;
59 pos = ftell(dev);
61 fseek(dev, block * 512, SEEK_SET);
63 fread(blk, 512, 1, dev);
65 fseek(dev, pos, SEEK_SET);
67 if (checksum(blk) != 0) {
68 /* printf("parthenope-install: Bad checksum at block: %d!\n", block);*/
69 return NULL;
72 return blk;
75 static struct RigidDiskBlock *read_rdb(FILE * dev,
76 struct RigidDiskBlock *blk,
77 uint32_t block)
79 uint32_t pos;
81 pos = ftell(dev);
82 fseek(dev, block * 512, SEEK_SET);
83 fread(blk, sizeof(struct RigidDiskBlock), 1, dev);
84 fseek(dev, pos, SEEK_SET);
86 return blk;
89 struct RigidDiskBlock *find_rdb(FILE * dev, uint32_t * rdb_block)
91 uint32_t i;
92 struct RigidDiskBlock *rdb;
94 rdb = malloc(512);
96 for (i = 0; i < RDB_LOCATION_LIMIT; i++) {
97 if (read_block(dev, (struct AmigaBlock *)rdb, i) == NULL
98 || rdb->rdb_ID != IDNAME_RIGIDDISK)
99 continue;
100 if (checksum((struct AmigaBlock *)rdb) != 0) {
101 printf("parthenope-install: Bad checksum at block "
102 "%d\n", i);
103 continue;
105 *rdb_block = i;
106 return read_rdb(dev, rdb, i);
109 free(rdb);
110 return NULL;
113 int next_free_block(FILE * dev, uint32_t * block, uint32_t * free_pointer,
114 uint32_t nblocks)
116 struct AmigaBlock *blk;
118 blk = malloc(512);
120 do {
121 (*free_pointer)++;
122 if (read_block(dev, blk, *free_pointer) == NULL)
123 continue;
124 } while (!IS_FREE(blk) && *free_pointer < nblocks);
126 if (IS_FREE(blk)) {
127 free(blk);
128 *block = *free_pointer;
129 return *block;
132 free(blk);
134 return -1;
137 void write_block(FILE * dev, void *blk, uint32_t block)
139 fseek(dev, block * 512, SEEK_SET);
140 fwrite(blk, 1, 512, dev);
143 void erase_slb(FILE * dev, struct RigidDiskBlock *rdb)
145 uint32_t block;
146 struct AmigaBlock *blk;
148 printf("parthenope-install: Erasing old slb ...");
149 fflush(stdout);
151 blk = malloc(512);
152 for (block = rdb->rdb_BootBlockList;
153 block != IDNAME_FREE
154 && read_block(dev, blk, block) != NULL
155 && blk->amiga_ID == IDNAME_BOOT;
156 block = ((struct BootstrapCodeBlock *)blk)->bcb_Next) {
157 blk->amiga_ID = IDNAME_FREE;
158 calculate_checksum(blk);
159 write_block(dev, blk, block);
163 printf(" done!\n");
167 void install_slb(FILE * dev, struct RigidDiskBlock *rdb, uint32_t * slb,
168 uint32_t slb_size)
170 uint32_t offset;
171 uint32_t block, next_block, free_block_pointer;
172 struct BootstrapCodeBlock *blk;
174 printf("parthenope-install: Writing new slb ...");
175 fflush(stdout);
177 free_block_pointer = 0;
179 if (next_free_block(dev, &block, &free_block_pointer,
180 rdb->rdb_RDBBlocksHi - rdb->rdb_RDBBlocksLo) < 0) {
181 printf("parthenope-install: Not enough free blocks!\n");
182 return;
185 rdb->rdb_BootBlockList = block;
187 blk = malloc(512);
188 for (offset = 0; offset < slb_size; offset += 123) {
189 if (next_free_block(dev, &next_block, &free_block_pointer,
190 rdb->rdb_RDBBlocksHi - rdb->rdb_RDBBlocksLo)
191 < 0) {
193 printf("parthenope-install: Not enough free blocks!\n");
195 return;
198 blk->bcb_ID = IDNAME_BOOT;
199 blk->bcb_SummedLongs = 128;
200 blk->bcb_HostID = 0;
201 blk->bcb_Next = next_block;
202 if (slb_size - offset <= 123) {
203 blk->bcb_SummedLongs = 5 + slb_size - offset;
204 blk->bcb_Next = IDNAME_FREE;
206 memmove(blk->bcb_LoadData, slb + offset, 123
207 * sizeof(uint32_t));
208 calculate_checksum((struct AmigaBlock *) blk);
209 write_block(dev, blk, block);
210 block = next_block;
213 printf(" done!\n");
216 int main(int argc, char **argv)
218 FILE *dev, *f;
219 struct RigidDiskBlock *rdb;
220 uint32_t rdb_block, *slb, slb_size;
221 struct stat st;
223 if (argc != 2) {
224 fprintf(stderr, "parthenope-install: Usage: %s "
225 "/path/to/Parthenope!\n", argv[0]);
226 return -1;
229 dev = fopen("/dev/sda", "w+");
230 if (dev == NULL) {
231 fprintf(stderr, "parthenope-install: Cannot open /dev/sda!\n");
232 return -1;
235 rdb = find_rdb(dev, &rdb_block);
236 if (rdb == NULL) {
237 fprintf(stderr, "parthenope-install: Cannot find RDB!\n");
238 fclose(dev);
239 return -1;
242 if (lstat(argv[1], &st) < 0) {
243 fprintf(stderr,
244 "parthenope-install: Cannot stat %s!\n", argv[1]);
245 free(rdb);
246 fclose(dev);
247 return -1;
250 f = fopen(argv[1], "r");
251 if (f == NULL) {
252 fprintf(stderr,
253 "parthenope-install: Cannot open %s!\n", argv[1]);
254 free(rdb);
255 fclose(dev);
256 return -1;
259 slb_size = st.st_size / sizeof(uint32_t);
260 slb = malloc(st.st_size);
262 fread(slb, 1, st.st_size, f);
263 fclose(f);
265 erase_slb(dev, rdb);
266 install_slb(dev, rdb, slb, slb_size);
267 calculate_checksum((struct AmigaBlock *) rdb);
268 write_block(dev, rdb, rdb_block);
269 free(rdb);
270 fclose(dev);
272 return 0;