New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / workbench / c / Install.c
blobe4c1c7609899c5b45c59ced4615dcd69d4372d61
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <string.h>
10 #include <stdio.h>
12 #include <proto/dos.h>
13 #include <proto/exec.h>
15 #include <devices/newstyle.h>
16 #include <devices/trackdisk.h>
17 #include <dos/dos.h>
18 #include <dos/dosextens.h>
19 #include <dos/filehandler.h>
20 #include <exec/errors.h>
21 #include <exec/io.h>
22 #include <exec/memory.h>
23 #include <exec/types.h>
24 #include <exec/ports.h>
25 #include <aros/macros.h>
27 struct Volume {
28 STRPTR drivename;
29 struct MsgPort *mp;
30 struct IOExtTD *iotd;
31 struct FileSysStartupMsg *fssm;
32 ULONG readcommand;
33 ULONG writecommand;
34 ULONG startblock;
35 ULONG countblock;
36 UWORD SizeBlock;
37 UBYTE flags;
38 ULONG *blockbuffer;
41 #define VF_IS_TRACKDISK (1<<0)
42 #define VF_MOVE_BB (1<<1)
44 struct BlockNode {
45 ULONG sector;
46 UWORD count;
47 UWORD seg_adr;
50 ULONG stage2_firstblock[128];
52 int readwriteBlock
54 struct Volume *volume,
55 ULONG block, APTR buffer, ULONG length,
56 ULONG command
59 UQUAD offset;
60 ULONG retval;
62 volume->iotd->iotd_Req.io_Command = command;
63 volume->iotd->iotd_Req.io_Length = length;
64 volume->iotd->iotd_Req.io_Data = buffer;
65 offset = (UQUAD)(volume->startblock+block)*(volume->SizeBlock*4);
66 volume->iotd->iotd_Req.io_Offset = offset & 0xFFFFFFFF;
67 volume->iotd->iotd_Req.io_Actual = offset>>32;
68 retval = DoIO((struct IORequest *)&volume->iotd->iotd_Req);
69 if (volume->flags & VF_IS_TRACKDISK)
71 volume->iotd->iotd_Req.io_Command = TD_MOTOR;
72 volume->iotd->iotd_Req.io_Length = 0;
73 DoIO((struct IORequest *)&volume->iotd->iotd_Req);
75 return retval;
78 ULONG collectBlockList(struct Volume *volume, ULONG block, struct BlockNode *blocklist) {
79 ULONG retval, first_block;
80 WORD blk_count,count;
81 UWORD i;
83 #warning "TODO: logical/physical blocks"
85 initialze stage2-blocklist
86 (it is NULL-terminated)
88 for (blk_count=-1;blocklist[blk_count].sector!=0;blk_count--)
89 blocklist[blk_count].sector = 0;
91 the first block of stage2 will be stored in stage1
92 so skip the first filekey in the first loop
94 #warning "Block read twice"
95 retval=readwriteBlock
97 volume, block, volume->blockbuffer, volume->SizeBlock*4,
98 volume->readcommand
100 i = volume->SizeBlock - 52;
101 first_block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock-51]);
102 blk_count=0;
103 do {
104 retval=readwriteBlock
106 volume, block, volume->blockbuffer, volume->SizeBlock*4,
107 volume->readcommand
109 if (retval)
111 printf("ReadError %ld\n", retval);
112 return 0;
114 while ((i>=6) && (volume->blockbuffer[i]))
117 if current sector follows right after last sector
118 then we don't need a new element
120 if (
121 (blocklist[blk_count].sector) &&
122 ((blocklist[blk_count].sector+blocklist[blk_count].count)==
123 AROS_BE2LONG(volume->blockbuffer[i]))
126 blocklist[blk_count].count += 1;
128 else
130 blk_count--; /* decrement first */
131 if (blocklist[blk_count-1].sector != 0)
133 printf("There is no more space to save blocklist in stage2\n");
134 return 0;
136 blocklist[blk_count].sector = AROS_BE2LONG(volume->blockbuffer[i]);
137 blocklist[blk_count].count = 1;
139 i--;
141 i = volume->SizeBlock - 51;
142 block = AROS_BE2LONG(volume->blockbuffer[volume->SizeBlock - 2]);
143 } while (block);
145 blocks in blocklist are relative to the first
146 sector of the HD (not partition)
148 i = 0;
149 for (count=-1;count>=blk_count;count--)
151 blocklist[count].sector += volume->startblock;
152 blocklist[count].seg_adr = 0x820 + (i*32);
153 i += blocklist[count].count;
155 return first_block;
158 /*************************************
159 Name : installStageFiles
160 Descr.: install stage1 and initialize stage2
161 Input : volume - the volume to install on
162 use_mbr - flag to use MBR
163 stage2_drive - the unit stage2 is located
164 **************************************/
165 void installStageFiles(struct Volume *volume, LONG use_mbr, UBYTE stage2_drive) {
166 char stagename[256];
167 struct FileInfoBlock fib;
168 BPTR fh, fh2;
169 ULONG block,retval;
170 ULONG error=0;
171 STRPTR errstr=NULL;
174 strcpy(stagename, (char *)volume->drivename);
175 strcat(stagename, "Boot/grub/stage2");
176 fh = Open(stagename,MODE_OLDFILE);
177 if (fh)
179 if (Examine(fh, &fib))
181 if (Read(fh, stage2_firstblock, 512) == 512)
183 if ((volume->flags & VF_MOVE_BB) && !use_mbr)
185 readwriteBlock
187 volume, 1, volume->blockbuffer, 512,
188 volume->writecommand
191 if (
193 block=collectBlockList
195 volume, fib.fib_DiskKey,
196 (struct BlockNode *)&stage2_firstblock[128]
201 if (Seek(fh, 0, OFFSET_BEGINNING)!=-1)
203 if (Write(fh, stage2_firstblock, 512)==512)
205 strcpy(stagename, (char *)volume->drivename);
206 strcat(stagename, "Boot/grub/stage1");
207 fh2 = Open(stagename, MODE_OLDFILE);
208 if (fh2)
210 if (Read(fh2, volume->blockbuffer, 512) == 512)
212 volume->blockbuffer[17]=block;
213 retval = 0;
214 if (use_mbr)
216 volume->blockbuffer[17] += volume->startblock;
217 volume->startblock = 0;
218 retval = readwriteBlock
220 volume, 0,
221 stage2_firstblock, 512, volume->readcommand
223 /* copy BPB (BIOS Parameter Block)*/
224 CopyMem
226 (APTR)((char *)stage2_firstblock+0x3),
227 (APTR)((char *)volume->blockbuffer+0x3),
228 0x3B
230 /* copy partition table */
231 CopyMem
233 (APTR)((char *)stage2_firstblock+0x1BE),
234 (APTR)((char *)volume->blockbuffer+0x1BE),
235 0x40
237 /* store the drive num stage2 is stored on */
238 ((char *)volume->blockbuffer)[0x40] = stage2_drive+0x80;
240 if (retval==0)
242 retval = readwriteBlock
244 volume, 0,
245 volume->blockbuffer, 512, volume->writecommand
247 if (retval)
248 printf("WriteError %ld\n", retval);
250 else
251 printf("WriteErrro %ld\n", retval);
253 else
254 error = IoErr();
255 Close(fh2);
257 else
259 error = IoErr();
260 errstr = stagename;
263 else
264 error = IoErr();
266 else
267 error = IoErr();
270 else
272 error = IoErr();
273 errstr = stagename;
276 else
278 error = IoErr();
279 errstr = stagename;
281 Close(fh);
283 else
285 error = IoErr();
286 errstr = stagename;
288 if (error)
289 PrintFault(error, errstr);
292 void nsdCheck(struct Volume *volume) {
293 struct NSDeviceQueryResult nsdq;
294 UWORD *cmdcheck;
295 if (
297 (volume->startblock+volume->countblock)* /* last block */
298 (volume->SizeBlock*4/512) /* 1 portion (block) equals 512 (bytes) */
299 )>8388608)
301 nsdq.SizeAvailable=0;
302 nsdq.DevQueryFormat=0;
303 volume->iotd->iotd_Req.io_Command=NSCMD_DEVICEQUERY;
304 volume->iotd->iotd_Req.io_Data=&nsdq;
305 volume->iotd->iotd_Req.io_Length=sizeof(struct NSDeviceQueryResult);
306 if (DoIO((struct IORequest *)&volume->iotd->iotd_Req)==IOERR_NOCMD)
308 printf("Device doesn't understand NSD-Query\n");
310 else
312 if (
313 (volume->iotd->iotd_Req.io_Actual>sizeof(struct NSDeviceQueryResult)) ||
314 (volume->iotd->iotd_Req.io_Actual==0) ||
315 (volume->iotd->iotd_Req.io_Actual!=nsdq.SizeAvailable)
318 printf("WARNING wrong io_Actual using NSD\n");
320 else
322 if (nsdq.DeviceType != NSDEVTYPE_TRACKDISK)
323 printf("WARNING no trackdisk type\n");
324 for (cmdcheck=nsdq.SupportedCommands;*cmdcheck;cmdcheck++)
326 if (*cmdcheck == NSCMD_TD_READ64)
327 volume->readcommand = NSCMD_TD_READ64;
328 if (*cmdcheck == NSCMD_TD_WRITE64);
329 volume->writecommand = NSCMD_TD_WRITE64;
331 if (
332 (volume->readcommand!=NSCMD_TD_READ64) ||
333 (volume->writecommand!=NSCMD_TD_WRITE64)
335 printf("WARNING no READ64/WRITE64\n");
341 struct Volume *initVolume(STRPTR drivename, LONG use_mbr) {
342 struct Volume *volume=0;
343 struct FileSysStartupMsg *fssm;
344 struct DosList *dl;
345 struct DosEnvec *de;
346 struct DeviceNode *dn;
347 char dname[32];
348 UBYTE i;
349 ULONG error=0,retval;
350 STRPTR errstr=NULL;
352 for (i=0;(drivename[i]) && (drivename[i]!=':');i++)
353 dname[i]=drivename[i];
354 dname[i]=0;
355 dl = LockDosList(LDF_READ | LDF_DEVICES);
356 if (dl)
358 dn = (struct DeviceNode *)FindDosEntry(dl, dname, LDF_DEVICES);
359 UnLockDosList(LDF_READ | LDF_DEVICES);
360 if (dn)
362 if (IsFileSystem(drivename))
364 fssm = (struct FileSysStartupMsg *)BADDR(dn->dn_Startup);
365 if (use_mbr)
367 if (strcmp(AROS_BSTR_ADDR(fssm->fssm_Device),"ide.device")!=0)
369 error = ERROR_OBJECT_WRONG_TYPE;
370 errstr = AROS_BSTR_ADDR(fssm->fssm_Device);
372 else
374 if (fssm->fssm_Unit!=0)
376 error = ERROR_OBJECT_WRONG_TYPE;
377 errstr = "MBR can only be stored on the first HD";
381 if (error == 0)
383 volume = AllocVec(sizeof(struct Volume), MEMF_PUBLIC | MEMF_CLEAR);
384 if (volume)
386 volume->fssm = fssm;
387 volume->drivename = drivename;
388 volume->mp = CreateMsgPort();
389 if (volume->mp)
391 volume->iotd = (struct IOExtTD *)CreateIORequest(volume->mp, sizeof(struct IOExtTD));
392 if (volume->iotd)
394 de = volume->fssm->fssm_Environ;
395 volume->SizeBlock = de->de_SizeBlock;
396 volume->blockbuffer = AllocVec(volume->SizeBlock*4, MEMF_PUBLIC | MEMF_CLEAR);
397 if (volume->blockbuffer)
399 if (
400 OpenDevice
402 AROS_BSTR_ADDR(volume->fssm->fssm_Device),
403 volume->fssm->fssm_Unit,
404 (struct IORequest *)&volume->iotd->iotd_Req,
405 volume->fssm->fssm_Flags
406 )==0
409 if (strcmp(AROS_BSTR_ADDR(volume->fssm->fssm_Device), "trackdisk.device") == 0)
410 volume->flags |= VF_IS_TRACKDISK;
411 volume->startblock =
412 de->de_LowCyl*
413 de->de_Surfaces*
414 de->de_BlocksPerTrack;
415 volume->countblock =
418 de->de_HighCyl-de->de_LowCyl+1
419 )*de->de_Surfaces*de->de_BlocksPerTrack
420 )-1+de->de_Reserved;
421 volume->readcommand = CMD_READ;
422 volume->writecommand = CMD_WRITE;
423 nsdCheck(volume);
424 retval = readwriteBlock
426 volume, 0,
427 volume->blockbuffer, 512, volume->readcommand
429 if (retval == 0)
431 if ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)!=0x444F5300)
433 retval = readwriteBlock
435 volume, 1,
436 volume->blockbuffer, 512, volume->readcommand
439 else
440 volume->flags |= VF_MOVE_BB;
441 if (
442 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)==0x444F5300) &&
443 ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFF)>0)
446 return volume;
448 else
449 error = ERROR_NOT_A_DOS_DISK;
451 else
453 error = ERROR_UNKNOWN;
454 errstr = "Read Error";
457 else
459 error = ERROR_UNKNOWN;
460 errstr = "OpenDevice() Error";
462 FreeVec(volume->blockbuffer);
464 else
465 error = ERROR_NO_FREE_STORE;
467 else
468 error = ERROR_NO_FREE_STORE;
469 DeleteMsgPort(volume->mp);
471 else
472 error = ERROR_NO_FREE_STORE;
473 FreeVec(volume);
474 volume = 0;
476 else
477 error = ERROR_NO_FREE_STORE;
480 else
481 error = IoErr();
483 else
485 error = ERROR_OBJECT_NOT_FOUND;
486 errstr = dname;
489 else
491 error = ERROR_UNKNOWN;
492 errstr = "LockDosList Error";
494 PrintFault(error, errstr);
495 return 0;
498 void uninitVolume(struct Volume *volume) {
500 FreeVec(volume->blockbuffer);
501 CloseDevice((struct IORequest *)&volume->iotd->iotd_Req);
502 DeleteIORequest((struct IORequest *)volume->iotd);
503 DeleteMsgPort(volume->mp);
504 FreeVec(volume);
507 void checkBootCode(struct Volume *volume) {
508 printf("CHECK not implemented yet\n");
511 void removeBootCode(struct Volume *volume) {
512 ULONG retval;
514 retval = readwriteBlock
516 volume, 1,
517 volume->blockbuffer, 512, volume->readcommand
519 if (retval)
520 printf("ReadError %ld\n", retval);
521 else
523 if ((AROS_BE2LONG(volume->blockbuffer[0]) & 0xFFFFFF00)==0x444F5300)
525 retval = readwriteBlock
527 volume, 0,
528 volume->blockbuffer, 512, volume->writecommand
530 if (retval)
531 printf("WriteError %ld\n", retval);
536 int main(void) {
537 LONG myargs[5]={0,0,0,0,0};
538 struct RDArgs *rdargs;
539 struct Volume *volume;
541 rdargs = ReadArgs("DRIVE/A,NOBOOT/S,CHECK/S,FFS/S,MBR/S",myargs,NULL);
542 if (rdargs)
544 volume = initVolume((STRPTR)myargs[0], myargs[4]);
545 if (volume)
547 if (myargs[1])
548 removeBootCode(volume);
549 else if (myargs[2])
550 checkBootCode(volume);
551 else
552 installStageFiles(volume, myargs[4], volume->fssm->fssm_Unit);
553 uninitVolume(volume);
555 FreeArgs(rdargs);
557 else
558 PrintFault(IoErr(), NULL);
559 return 0;