========== amiga/programs #367, from talin, 9715 chars, Sun Feb 7 07:56:54 1988 Comment to 366. ---------- /*********************************************************************** * bootback.c - copies boot blocks to file, or files to boot blocks * * By Talin, otherwise known as David Joiner * * Note comments are only mostly serious * ***********************************************************************/ /* compiled like this: cc +l bootback ln bootback.o -lc32 */ #include "exec/types.h" #include "exec/memory.h" #include "libraries/dosextens.h" /* my DOS is bigger than your DOS */ #include "libraries/filehandler.h" #include "devices/trackdisk.h" /* But does it make a good frisbee? */ #include "arp/arpbase.h" #include "arp/arpfunctions.h" #define SCAT goto exit_pgm #define MAX_FILENAME 32 struct ArpBase *ArpBase; /* Mama! */ void *OpenLibrary(), /* Daddy! */ *AllocMem(); /* Cheetah! */ /* This is the stuff mother never told you about */ struct DevEnviron { ULONG TableSize, SizeBlock, SecOrg, NumHeads, SecsPerBlock, BlocksPerTrack, ReservedBlocks, Preface, Interleave, LowCylinder, UpperCylinder, NumBuffers, MemBufType; } *environ; ULONG blocksize; struct MsgPort *diskport, *CreatePort(); struct IOExtTD *diskreq, *CreateExtIO(); #define ADDR(a) (void *)( (int)a << 2) /* I don't like the standard macro */ /* This is a rather EVIL way to do this, but I can think of nothing else that will work in a reasonable fashion. Essentially what this does is take a name of a device or volume and returns the DeviceNode entry for that device, buy brute force searching through the AmigaDOS device list. For a volume, the search has to be done twice, and is rather kludgey. Works like a charm. I wish it worked like software instead. Once this is done, the caller can easily determine the device driver name for exec-level IO. (see main below). */ struct DeviceNode *get_device(name) char *name; { struct DeviceNode *dlist = NULL; char device_name[MAX_FILENAME+2]; short length; while (dlist = (struct DeviceNode *)GetDevInfo(dlist)) { length = BtoCStr(device_name,dlist->dn_Name,33); device_name[length++] = ':'; /* Appendix a Colon on the end */ device_name[length] = '\0'; /* and that other thing */ /* try to find a match with name */ if (Strcmp(name,device_name)==0) { if (dlist->dn_Type == DLT_DEVICE) return dlist; if (dlist->dn_Type == DLT_VOLUME) { struct Task *dev_task; char *task_name, *colon_name; struct MsgPort *proc; /* actually a Process, but those */ /* makes no sense anyway */ proc = (struct MsgPort *)dlist->dn_Task; /* Oooh, I remembered 'mp_SigTask' without looking it up...that's Scary. */ dev_task = proc->mp_SigTask; /* not very kosher */ colon_name = device_name; /* copy device name to here */ task_name = dev_task->tc_Node.ln_Name; /* BAD Talin! BAD! */ while (*task_name) *colon_name++ = *task_name++; /* copy */ *colon_name++ = ':'; /* put a colon on it, bud. */ *colon_name++ = '\0'; /* and stop it from bleeding */ return get_device(device_name); /* recursive but only once */ } return NULL; /* return NULL for assigns: */ } } return NULL; /* Negative, Will Robinson */ } extern struct WBStartup *WBenchMsg; wb_parse(); /* stub */ main(argc, argv) LONG argc; UBYTE **argv; { char driver_name[MAX_FILENAME+2]; ULONG error, /* open device error */ arg_device, /* which arg was the device */ arg_file; /* and which was the file? */ struct FileSysStartupMsg *fssm; /* filesys startup message */ struct DeviceNode *d1, /* Device node entries for */ *d2, /* arg1, arg2 and */ *dvc; /* whichever one we open */ struct FILE *save_file=NULL, *Open(); APTR buff=NULL; /* buffer for loaded blocks */ UBYTE device_open=0; /* flag is device was open */ diskport = NULL; diskreq = NULL; if (WBenchMsg) exit(0); /* HELL NO, WE WON'T GO! */ if (!(ArpBase = OpenLibrary("arp.library",0))) /* open up there, arp! */ { Write(Output(),"Can't find arp.library\n",23); /* You Varmit! */ exit(20); } if (argc != 3) /* check to make sure correct # of arguments */ { Printf("BootBack - Saves and restores custom boot blocks\n"); Printf("Usage:\n\n"); Printf("To save boot block: BootBack \n"); Printf("To restore boot block: BootBack \n"); SCAT; /* Take a powder */ } d1 = get_device(argv[1]); d2 = get_device(argv[2]); if (d1 && d2) { Printf("They can't BOTH be devices!\n"); SCAT; } if (!d1 && !d2) { Printf("Neither of those is a device, silly!\n"); SCAT; } if (d1) { dvc = d1; arg_device = 1; arg_file = 2; } if (d2) { dvc = d2; arg_device = 2; arg_file = 1; } fssm = ADDR(dvc->dn_Startup); if (!fssm) { Printf("Can't find device driver for <%s>.\n",argv[arg_device]); SCAT; } BtoCStr(driver_name,fssm->fssm_Device,33); environ = ADDR(fssm->fssm_Environ); blocksize = environ->SizeBlock * sizeof (LONG); /* BCPL foolishness */ if (arg_file == 1) save_file = Open(argv[arg_file],MODE_OLDFILE); else save_file = Open(argv[arg_file],MODE_NEWFILE); if (!save_file) { Printf("Can't open save file <%s>.\n",argv[arg_file]); SCAT; } /* Ah pity the foo don't have enough memory to run this program! */ buff = AllocMem(2 * blocksize,MEMF_CHIP); if (!buff) { Printf("Not enough memory.\n"); SCAT; } /* TILT! */ if (!(diskport = CreatePort(0,0)) || !(diskreq = CreateExtIO(diskport,sizeof (struct IOExtTD))) || (error = OpenDevice(driver_name,fssm->fssm_Unit, diskreq,fssm->fssm_Flags)) ) { Printf("Problems opening disk device...!\n"); if (error) Printf("Error = %d.\n",error); SCAT; /* get outta here, ya nut! */ } device_open = TRUE; Printf("%s opened.\n",driver_name); /* chatty but educational */ if (arg_file == 2) /* if filename was 2nd arg */ { if (load_track_range(0,2,buff)) /* 2 lumps please */ { Printf("Problem reading device...\n"); SCAT; } /* TOAST */ Write(save_file,"BOOTBLOC",8); /* id check for safety's sake */ Write(save_file,buff,2*blocksize); /* Doit Toit */ } else { char file_id[9]; /* id string */ Read(save_file,file_id,8); /* read id */ file_id[8] = 0; /* null terminate */ if (Strcmp(file_id,"BOOTBLOC")) { Printf("This file is NOT a saved boot block!\n"); SCAT; } Read(save_file,buff,2 * blocksize); if (save_track_range(0,2,buff)) /* Thou art Healed! A Miracle! */ { Printf("Problem writing device...\n"); SCAT; } /* Well, Almost */ } Printf("Done!\n"); exit_pgm: if (device_open) { motor_off(); CloseDevice(diskreq); } if (diskreq) DeleteExtIO(diskreq,sizeof (struct IOExtTD)); if (diskport) DeletePort(diskport); if (buff) FreeMem(buff,2 * blocksize); if (save_file) Close(save_file); if (ArpBase) CloseLibrary(ArpBase); } save_track_range(first_block,block_count,buffer) short first_block, block_count; char *buffer; { diskreq->iotd_Req.io_Length = (block_count * blocksize); diskreq->iotd_Req.io_Data = (APTR)buffer; diskreq->iotd_Req.io_Command = CMD_WRITE; diskreq->iotd_Req.io_Offset = (first_block * blocksize); DoIO(diskreq); return diskreq->iotd_Req.io_Error; } load_track_range(first_block,block_count,buffer) short first_block, block_count; char *buffer; { diskreq->iotd_Req.io_Length = (block_count * blocksize); diskreq->iotd_Req.io_Data = (APTR)buffer; diskreq->iotd_Req.io_Command = CMD_READ; diskreq->iotd_Req.io_Offset = (first_block * blocksize); DoIO(diskreq); return diskreq->iotd_Req.io_Error; } motor_off() { diskreq->iotd_Req.io_Length = 0; diskreq->iotd_Req.io_Command = TD_MOTOR; DoIO(diskreq); } #asm cseg include "arp/arpbase.i" public _ArpBase public _Printf _Printf move.l 4(sp),a0 lea 8(sp),a1 move.l _ArpBase,a6 jmp _LVOPrintf(a6) public _Strcmp _Strcmp move.l 4(sp),a0 move.l 8(sp),a1 move.l _ArpBase,a6 jmp _LVOStrcmp(a6) public _GetDevInfo _GetDevInfo move.l 4(sp),a2 move.l _ArpBase,a6 jmp _LVOGetDevInfo(a6) public _BtoCStr _BtoCStr move.l 4(sp),a0 move.l 8(sp),d0 move.l 12(sp),d1 move.l _ArpBase,a6 jmp _LVOBtoCStr(a6) #endasm /* That's all, folks! */