home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 112.lha / bootback.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  10KB  |  255 lines

  1.  
  2. ==========
  3. amiga/programs #367, from talin, 9715 chars, Sun Feb  7 07:56:54 1988
  4. Comment to 366. 
  5. ----------
  6. /***********************************************************************
  7.  * bootback.c - copies boot blocks to file, or files to boot blocks    *
  8.  * By Talin, otherwise known as David Joiner                           *
  9.  * Note comments are only mostly serious                               *
  10.  ***********************************************************************/
  11. /* compiled like this:
  12.     cc +l bootback
  13.     ln bootback.o -lc32
  14. */
  15.  
  16. #include "exec/types.h"
  17. #include "exec/memory.h"
  18. #include "libraries/dosextens.h"        /* my DOS is bigger than your DOS */
  19. #include "libraries/filehandler.h"
  20. #include "devices/trackdisk.h"          /* But does it make a good frisbee? */
  21.  
  22. #include "arp/arpbase.h"
  23. #include "arp/arpfunctions.h"
  24.  
  25. #define SCAT            goto exit_pgm
  26. #define MAX_FILENAME    32
  27.  
  28. struct ArpBase          *ArpBase;       /* Mama! */
  29. void                    *OpenLibrary(), /* Daddy! */
  30.                         *AllocMem();    /* Cheetah! */
  31.  
  32. /* This is the stuff mother never told you about */
  33.  
  34. struct DevEnviron {
  35.     ULONG   TableSize, SizeBlock, SecOrg, NumHeads,
  36.             SecsPerBlock, BlocksPerTrack, ReservedBlocks, Preface,
  37.             Interleave, LowCylinder, UpperCylinder, NumBuffers,
  38.             MemBufType;
  39. } *environ;
  40.  
  41. ULONG       blocksize;
  42.  
  43. struct MsgPort *diskport, *CreatePort();
  44. struct IOExtTD *diskreq, *CreateExtIO();
  45.  
  46. #define ADDR(a) (void *)( (int)a << 2)  /* I don't like the standard macro */
  47.  
  48. /*      This is a rather EVIL way to do this, but I can think of nothing
  49.     else that will work in a reasonable fashion.
  50.         Essentially what this does is take a name of a device or volume
  51.     and returns the DeviceNode entry for that device, buy brute force
  52.     searching through the AmigaDOS device list. For a volume, the
  53.     search has to be done twice, and is rather kludgey.
  54.         Works like a charm. I wish it worked like software instead.
  55.         Once this is done, the caller can easily determine the device
  56.     driver name for exec-level IO. (see main below).
  57. */
  58.  
  59. struct DeviceNode *get_device(name) char *name;
  60. {   struct DeviceNode   *dlist = NULL;
  61.     char                device_name[MAX_FILENAME+2];
  62.     short               length;
  63.  
  64.     while (dlist = (struct DeviceNode *)GetDevInfo(dlist))
  65.     {   length = BtoCStr(device_name,dlist->dn_Name,33);
  66.         device_name[length++] = ':';    /* Appendix a Colon on the end */
  67.         device_name[length] = '\0';     /* and that other thing */
  68.  
  69.             /* try to find a match with name */
  70.         if (Strcmp(name,device_name)==0)
  71.         {   if (dlist->dn_Type == DLT_DEVICE) return dlist;
  72.             if (dlist->dn_Type == DLT_VOLUME)
  73.             {   struct Task *dev_task;
  74.                 char *task_name, *colon_name;
  75.                 struct MsgPort *proc;       /* actually a Process, but those */
  76.                                             /* makes no sense anyway */
  77.                 proc = (struct MsgPort *)dlist->dn_Task;
  78.                     /* Oooh, I remembered 'mp_SigTask' without looking it
  79.                         up...that's Scary. */
  80.  
  81.                 dev_task = proc->mp_SigTask;    /* not very kosher */
  82.                 colon_name = device_name;       /* copy device name to here */
  83.                 task_name = dev_task->tc_Node.ln_Name;  /* BAD Talin! BAD! */
  84.                 while (*task_name) *colon_name++ = *task_name++;    /* copy */
  85.                 *colon_name++ = ':';            /* put a colon on it, bud. */
  86.                 *colon_name++ = '\0';           /* and stop it from bleeding */
  87.                 return get_device(device_name); /* recursive but only once */
  88.             }
  89.             return NULL;                        /* return NULL for assigns: */
  90.         }
  91.     }
  92.     return NULL;                                /* Negative, Will Robinson */
  93. }
  94.  
  95. extern struct WBStartup *WBenchMsg;
  96.  
  97. wb_parse();                                        /* stub */
  98.  
  99. main(argc, argv) LONG argc; UBYTE **argv;
  100. {   char                        driver_name[MAX_FILENAME+2];
  101.     ULONG                       error,          /* open device error */
  102.                                 arg_device,     /* which arg was the device */
  103.                                 arg_file;       /* and which was the file? */
  104.     struct FileSysStartupMsg    *fssm;          /* filesys startup message */
  105.     struct DeviceNode           *d1,            /* Device node entries for */
  106.                                 *d2,            /*    arg1, arg2 and       */
  107.                                 *dvc;           /*    whichever one we open */
  108.     struct FILE                 *save_file=NULL, *Open();
  109.     APTR                        buff=NULL;      /* buffer for loaded blocks */
  110.     UBYTE                       device_open=0;  /* flag is device was open */
  111.  
  112.     diskport = NULL; diskreq = NULL;
  113.  
  114.     if (WBenchMsg) exit(0);                     /* HELL NO, WE WON'T GO! */
  115.  
  116.     if (!(ArpBase = OpenLibrary("arp.library",0)))  /* open up there, arp! */
  117.     {   Write(Output(),"Can't find arp.library\n",23);  /* You Varmit! */
  118.         exit(20);
  119.     }
  120.  
  121.     if (argc != 3)          /* check to make sure correct # of arguments */
  122.     {   Printf("BootBack - Saves and restores custom boot blocks\n");
  123.         Printf("Usage:\n\n");
  124.         Printf("To save boot block:      BootBack <device> <file>\n");
  125.         Printf("To restore boot block:   BootBack <file> <device>\n");
  126.         SCAT;                               /* Take a powder */
  127.     }
  128.  
  129.     d1 = get_device(argv[1]);
  130.     d2 = get_device(argv[2]);
  131.  
  132.     if (d1 && d2) { Printf("They can't BOTH be devices!\n"); SCAT; }
  133.     if (!d1 && !d2) { Printf("Neither of those is a device, silly!\n"); SCAT; }
  134.  
  135.     if (d1) { dvc = d1; arg_device = 1; arg_file = 2; }
  136.     if (d2) { dvc = d2; arg_device = 2; arg_file = 1; }
  137.  
  138.     fssm = ADDR(dvc->dn_Startup);
  139.     if (!fssm)
  140.     { Printf("Can't find device driver for <%s>.\n",argv[arg_device]); SCAT; }
  141.  
  142.     BtoCStr(driver_name,fssm->fssm_Device,33);
  143.     environ = ADDR(fssm->fssm_Environ);
  144.     blocksize = environ->SizeBlock * sizeof (LONG);     /* BCPL foolishness */
  145.  
  146.     if (arg_file == 1) save_file = Open(argv[arg_file],MODE_OLDFILE);
  147.     else save_file = Open(argv[arg_file],MODE_NEWFILE);
  148.  
  149.     if (!save_file)
  150.     {   Printf("Can't open save file <%s>.\n",argv[arg_file]); SCAT; }
  151.  
  152.         /* Ah pity the foo don't have enough memory to run this program! */
  153.     buff = AllocMem(2 * blocksize,MEMF_CHIP);
  154.     if (!buff) { Printf("Not enough memory.\n"); SCAT; }    /* TILT! */
  155.  
  156.     if (!(diskport = CreatePort(0,0)) ||
  157.         !(diskreq = CreateExtIO(diskport,sizeof (struct IOExtTD))) ||
  158.         (error = OpenDevice(driver_name,fssm->fssm_Unit,
  159.                             diskreq,fssm->fssm_Flags)) )
  160.     {   Printf("Problems opening disk device...!\n");
  161.         if (error) Printf("Error = %d.\n",error);
  162.         SCAT;                               /* get outta here, ya nut! */
  163.     }
  164.     device_open = TRUE;
  165.     Printf("%s opened.\n",driver_name);     /* chatty but educational */
  166.  
  167.     if (arg_file == 2)                      /* if filename was 2nd arg */
  168.     {   if (load_track_range(0,2,buff))     /* 2 lumps please */
  169.         {   Printf("Problem reading device...\n"); SCAT; }  /* TOAST */
  170.         Write(save_file,"BOOTBLOC",8);      /* id check for safety's sake */
  171.         Write(save_file,buff,2*blocksize);  /* Doit Toit */
  172.     }
  173.     else
  174.     {   char file_id[9];                    /* id string */
  175.         Read(save_file,file_id,8);          /* read id */
  176.         file_id[8] = 0;                     /* null terminate */
  177.         if (Strcmp(file_id,"BOOTBLOC"))
  178.         {   Printf("This file is NOT a saved boot block!\n"); SCAT; }
  179.         Read(save_file,buff,2 * blocksize);
  180.         if (save_track_range(0,2,buff))     /* Thou art Healed! A Miracle! */
  181.         {   Printf("Problem writing device...\n"); SCAT; }  /* Well, Almost */
  182.     }
  183.  
  184.     Printf("Done!\n");
  185. exit_pgm:
  186.     if (device_open) { motor_off(); CloseDevice(diskreq); }
  187.     if (diskreq) DeleteExtIO(diskreq,sizeof (struct IOExtTD));
  188.     if (diskport) DeletePort(diskport);
  189.     if (buff) FreeMem(buff,2 * blocksize);
  190.     if (save_file) Close(save_file);
  191.     if (ArpBase) CloseLibrary(ArpBase);
  192. }
  193.  
  194. save_track_range(first_block,block_count,buffer)
  195.     short first_block, block_count; char *buffer;
  196. {   diskreq->iotd_Req.io_Length = (block_count * blocksize);
  197.     diskreq->iotd_Req.io_Data = (APTR)buffer;
  198.     diskreq->iotd_Req.io_Command = CMD_WRITE;
  199.     diskreq->iotd_Req.io_Offset = (first_block * blocksize);
  200.     DoIO(diskreq);
  201.     return diskreq->iotd_Req.io_Error;
  202. }
  203.  
  204. load_track_range(first_block,block_count,buffer)
  205.     short first_block, block_count; char *buffer;
  206. {   diskreq->iotd_Req.io_Length = (block_count * blocksize);
  207.     diskreq->iotd_Req.io_Data = (APTR)buffer;
  208.     diskreq->iotd_Req.io_Command = CMD_READ;
  209.     diskreq->iotd_Req.io_Offset = (first_block * blocksize);
  210.     DoIO(diskreq);
  211.     return diskreq->iotd_Req.io_Error;
  212. }
  213.  
  214. motor_off()
  215. {   diskreq->iotd_Req.io_Length = 0;
  216.     diskreq->iotd_Req.io_Command = TD_MOTOR;
  217.     DoIO(diskreq);
  218. }
  219.  
  220. #asm
  221.             cseg
  222.             include "arp/arpbase.i"
  223.  
  224.             public  _ArpBase
  225.  
  226.             public  _Printf
  227. _Printf     move.l  4(sp),a0
  228.             lea     8(sp),a1
  229.             move.l  _ArpBase,a6
  230.             jmp     _LVOPrintf(a6)
  231.  
  232.             public  _Strcmp
  233. _Strcmp     move.l  4(sp),a0
  234.             move.l  8(sp),a1
  235.             move.l  _ArpBase,a6
  236.             jmp     _LVOStrcmp(a6)
  237.  
  238.             public  _GetDevInfo
  239. _GetDevInfo move.l  4(sp),a2
  240.             move.l  _ArpBase,a6
  241.             jmp     _LVOGetDevInfo(a6)
  242.  
  243.             public  _BtoCStr
  244. _BtoCStr    move.l  4(sp),a0
  245.             move.l  8(sp),d0
  246.             move.l  12(sp),d1
  247.             move.l  _ArpBase,a6
  248.             jmp     _LVOBtoCStr(a6)
  249.  
  250. #endasm
  251.  
  252. /* That's all, folks! */
  253. No more unread
  254. Hit <RETURN> for next
  255. R: