home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Micro R&D 1
/
MicroRD-CD-ROM-Vol1-1994.iso
/
disktools
/
moni
/
bb20.lzh
/
BB
/
BB.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-18
|
10KB
|
545 lines
/*
* BB.c - bootblock management: reads, installs and fix checksums.
*
* Bruno Costa - 5 Dec 89 - 22 Jul 91
*
*/
#include <exec/types.h>
#include <exec/io.h>
#include <devices/bootblock.h>
#include <devices/trackdisk.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <ctype.h>
#include <string.h>
typedef unsigned char byte;
#if 0
#include "bootblock.h"
#else
byte bootblock[] = { /* standard AmigaDOS bootblock */
'D', 'O', 'S', 0,
0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
0x00, 0x00
};
#endif
byte doPAL[] = {
0x33, 0xfc, 0x00, 0x20, 0x00, 0xdf, 0xf1, 0xdc /* move.W #$20,$dff1dc */
};
#define BBSIZE 1024
#define MAXNAME 100
#define FIX 1
#define SHOW 2
#define INSTALL 3
#define PAL 4
#define READ 5
void print (char *msg);
void newline (void);
void xprint (unsigned long n);
void copyright (void);
void help (void);
void notify (char *msg);
void bbdump (byte *buffer);
unsigned long checksum (byte *buffer);
int bbinstall (struct IOStdReq *disk, byte *buffer);
int bbread (struct IOStdReq *disk, byte *buffer);
int fileread (char *name, byte *buf);
int filewrite (char *name, byte *buf);
void waitenter (void);
#define abort(x) {errnum = x; goto cleanup;}
void main (int argc, char *argv[])
{
byte *buf = NULL; /* disk buffer for bootblocks */
struct Port *diskport = NULL; /* trackdisk's message port */
struct IOStdReq *diskreq = NULL; /* trackdisk's IO request */
int errnum = 0;
int unit = -1;
int batch = TRUE, action = SHOW;
char bbname[MAXNAME], data[MAXNAME];
long error;
int c;
/*
* Command line processing
*/
if (argc == 1)
{
copyright ();
help ();
abort (5);
}
while (c = getoption (argc, argv, "ir", "acshpd", data))
if (c < 0)
{
notify ("unknown option");
help ();
abort (10);
}
else if (c == 1)
{
if (isdigit (data[0]))
unit = data[0] - '0';
else if (tolower (data[0]) == 'd' && tolower (data[1]) == 'f' &&
isdigit (data[2]))
unit = data[2] - '0';
else
{
help ();
abort (10);
}
}
else
switch (c)
{
case 'i':
action = INSTALL;
strcpy (bbname, data);
break;
case 'd':
action = INSTALL;
bbname[0] = '\0';
break;
case 'r':
action = READ;
strcpy (bbname, data);
break;
case 'a':
batch = FALSE;
break;
case 'c':
action = FIX;
break;
case 's':
action = SHOW;
break;
case 'p':
action = PAL;
break;
case 'h':
help ();
abort (10);
break;
}
if (unit < 0 || unit > 3)
{
notify ("Bad drive number");
abort (10);
}
/*
* Trackdisk I/O setup
*/
buf = AllocMem (BBSIZE, MEMF_CHIP | MEMF_CLEAR);
diskport = CreatePort (0, 0);
diskreq = CreateStdIO (diskport);
if (!buf || !diskport || !diskreq)
{
notify ("memory");
abort (30);
}
error = OpenDevice ("trackdisk.device", (long)unit, diskreq, 0);
if (error > 0)
{
notify ("trackdisk");
abort (20);
}
if (!batch) /* 1 2 */
{ /* 012345678901234567890123456789 */
char tmp[60] = "Please insert disk in DF9: and press ENTER ...";
tmp[24] = unit + '0';
print (tmp);
waitenter ();
}
/*
* Action processing
*/
switch (action)
{
case FIX:
if (!bbread (diskreq, buf))
abort (20);
print ("Old checksum = 0x");
xprint (((unsigned long *)buf)[1]);
newline ();
checksum (buf);
print ("New checksum = 0x");
xprint (((unsigned long *)buf)[1]);
newline ();
if (!bbinstall (diskreq, buf))
abort (20);
break;
case PAL:
print ("warning: this may make your bootblock unusable!\n");
print (" remove disk or press ENTER to continue:");
waitenter ();
if (!bbread (diskreq, buf))
abort (20);
memmove (buf + 12 + sizeof (doPAL), buf + 12, BBSIZE - 12 - sizeof (doPAL));
memcpy (buf + 12, doPAL, sizeof (doPAL));
checksum (buf);
if (!bbinstall (diskreq, buf))
abort (20);
break;
case INSTALL:
if (bbname[0] == '\0')
CopyMem (bootblock, buf, sizeof(bootblock)); /* my bootblock */
else
if (!fileread (bbname, buf))
abort (20);
checksum (buf); /* be sure that checksum is correct */
if (!bbinstall (diskreq, buf))
abort (20);
break;
case READ:
if (bbname[0] == '\0')
notify ("no filename given");
else
if (!bbread (diskreq, buf) || !filewrite (bbname, buf))
abort (20);
break;
case SHOW:
if (!bbread (diskreq, buf))
abort (20);
bbdump (buf);
break;
}
cleanup:
if (diskreq)
{
if (diskreq->io_Device)
CloseDevice (diskreq);
DeleteStdIO (diskreq);
}
if (diskport)
DeletePort (diskport);
if (buf)
FreeMem (buf, BBSIZE);
}
int fileread (char *name, byte *buf)
{
BPTR f;
long error;
f = Open (name, MODE_OLDFILE);
if (f)
{
error = Read (f, buf, BBSIZE);
Close (f);
}
if (!f || error == 0 || error == -1)
{
notify ("could not read custom bootblock file");
return FALSE;
}
else
return TRUE;
}
int filewrite (char *name, byte *buf)
{
BPTR f;
long error;
f = Open (name, MODE_NEWFILE);
if (f)
{
error = Write (f, buf, BBSIZE);
Close (f);
}
if (!f || error != BBSIZE)
{
notify ("could not write custom bootblock file");
return FALSE;
}
else
return TRUE;
}
/*
* waits for the ENTER key to be pressed
*/
void waitenter (void)
{
char dummy[2];
(void)Read (Input(), dummy, 2);
}
/*
* prints any message
*/
void print (char *msg)
{
Write (Output(), msg, strlen (msg));
}
/*
* prints a newline
*/
void newline (void)
{
Write (Output(), "\n", 1);
}
/*
* prints a copyright message
*/
void copyright (void)
{
print ("\x1b[33mBB v2.0\x1b[31m - \xa9 1989 by Bruno Costa\n");
}
/*
* prints a help message
*/
void help (void)
{
print ("usage: BB [-acshpd] [-i<filename>] [-r<filename>] <drivename>\n");
print ("\tr = read bootblock\n");
print ("\ti = install new bootblock\n");
print ("\td = install a DOS bootblock\n");
print ("\tc = fix bootblock checksum\n");
print ("\ts = show bootblock (default)\n");
print ("\tp = adds PAL booter to bootblock\n");
print ("\ta = asks for disk insertion before actions\n");
print ("\th = prints this help message\n");
}
/*
* notifies an error
*/
void notify (char *msg)
{
print ("BB: ");
print (msg);
newline ();
}
/*
* prints an hexadecimal number
*/
void xprint (unsigned long n)
{
int i;
char tmp[10];
static char xdigit[17] = "0123456789ABCDEF";
for (i = 7; i >= 0; i--)
{
tmp[i] = xdigit[n & 0x0000000f];
n = n >> 4;
}
tmp[8] = '\0';
print (tmp);
}
/*
* dumps the given bootblock in a readable form
*/
void bbdump (byte *buffer)
{
register int i, j;
char c, line[80];
unsigned long cksum;
cksum = ((unsigned long *)buffer)[1];
print (" Current checksum = 0x");
xprint (cksum);
print (" Correct checksum = 0x");
xprint (checksum (buffer));
((unsigned long *)buffer)[1] = cksum; /* restore old checksum */
newline ();
newline ();
for (i = 0; i < 16; i++)
{
for (j = 0; j < 64; j++)
{
c = buffer[i * 64 + j];
if (isprint (c))
line[j] = c;
else
line[j] = '.';
}
line[j] = '\0';
print (" ");
print (line);
newline ();
}
}
/*
* updates bootblock checksum in given buffer
*/
unsigned long checksum (byte *buffer)
{
register long sum, lastsum;
register int a;
unsigned long *ptr;
ptr = (long *)buffer;
if (ptr[0] != ID_DOS_DISK) /* not a DOS0 disk ? */
return 0;
ptr[1] = 0; /* clear buffer checksum */
sum = 0;
for (a = 0; a < 256; a++)
{
lastsum = sum;
sum = sum + ptr[a];
if (lastsum > sum)
sum++;
}
if (lastsum > 0)
ptr[1] = - sum - 1;
else
ptr[1] = - sum; /* sum + checksum must be 0 */
return ptr[1];
}
/*
* install bootblock in buffer into given disk
*/
int bbinstall (struct IOStdReq *disk, byte *buffer)
{
int error;
disk->io_Command = TD_PROTSTATUS; /* check write protection */
DoIO (disk);
if (disk->io_Actual != 0)
{
notify ("disk is write-protected");
return (FALSE);
};
error = 0;
disk->io_Length = BBSIZE;
disk->io_Data = (APTR)buffer;
disk->io_Command = CMD_WRITE;
disk->io_Offset = 0;
DoIO (disk);
error = disk->io_Error;
if (error < 19)
{
disk->io_Command = CMD_UPDATE; /* flush buffer to disk */
DoIO (disk);
error = disk->io_Error;
};
if (error < 19)
{
disk->io_Length = 0;
disk->io_Command = ETD_MOTOR; /* turn motor off */
DoIO (disk);
error = disk->io_Error;
};
if (error < 19)
return (TRUE);
else
{
notify ("could not install bootblock");
return (FALSE);
}
}
/*
* reads a bootblock (from given disk IO request) into buffer
*/
int bbread (struct IOStdReq *disk, byte *buffer)
{
disk->io_Command = CMD_READ;
disk->io_Data = (APTR)buffer;
disk->io_Length = BBSIZE;
disk->io_Offset = 0;
DoIO (disk);
if (disk->io_Error > 0)
{
notify ("could not read bootblock");
return (FALSE);
}
else
{
disk->io_Length = 0;
disk->io_Command = TD_MOTOR;
DoIO (disk);
return (TRUE);
}
}