
/*      mkboot - make boot sectors
                                        Author: Normand Mc Guire        */

extern  long    bios();
extern  long    xbios();
extern  long    gemdos();

#define Floprd(a,b,c,d,e,f,g)   xbios(8,a,b,c,d,e,f,g)
#define Flopwr(a,b,c,d,e,f,g)   xbios(9,a,b,c,d,e,f,g)
#define Protobt(a,b,c,d)        xbios(18,a,b,c,d)
#define Cconws(a)       gemdos(0x9,a)
#define Fopen(a,b)      gemdos(0x3d,a,b)
#define Fclose(a)       gemdos(0x3e,a)
#define Fread(a,b,c)    gemdos(0x3f,a,b,c)

#define O_RDONLY        0               /* GEMDOS Fopen parameter       */

#define SECT_SIZE       512
#define BOOT_DEV        0
#define BOOT_SECT       1
#define BOOT_TRK        0
#define BOOT_SIDE       0
#define NBOOT_SECT      1               /* number of boot sector        */
#define BOOT_SIZE       480             /* maximum boot program size    */
#define BOOT_FILE       "boot.prg"      /* default boot filename        */
#define BOOT_START      0x1e            /* start address of boot prg in */
                                        /* boot sector                  */

#define AOUT_LEN        28              /* ST loader information len at */
                                        /* the start of executable file */

char    buffer[SECT_SIZE];              /* boot sector I/O buffer       */
char    *boot_prg=BOOT_FILE;            /* boot program name            */
int     boot_fd;                        /* bootfile file descriptor     */

main(argc, argv)

int     argc;
char    *argv[];

        {
        if ( argc > 2 )         /* too many arguments                   */
                use_error();
        if ( argc == 2 )        /* boot program filename argument       */
                boot_prg=argv[1];

        openbf();               /* open boot program file               */
        readbs();               /* read boot sector                     */
        readbf();               /* read boot file into buffer           */
        fmtbb();                /* format boot buffer                   */
        writebs();              /* write back boot sector               */
        closebf();              /* close boot program file              */
        Cconws("Disk now has an executable boot sector\r\n");
        exit(0);
        }

/* opens the boot file */

openbf()

        {
        if ( (boot_fd=Fopen(boot_prg, O_RDONLY)) < 0 )
                {
                Cconws(boot_prg);
                Cconws(": cannot open\r\n");
                exit(1);
                }
        }

/* reads the boot sector into the buffer */

readbs()

        {
        int     s;
        long    filler;

        if ( (s=Floprd(buffer, filler, BOOT_DEV, BOOT_SECT, BOOT_TRK,
                BOOT_SIDE, NBOOT_SECT)) < 0 )
                {
                Cconws("mkboot: cannot read boot sector\r\n");
                exit(1);
                }
        }

/* read the boot file in its buffer area. First read the loader
   information (AOUT_LEN bytes), and then the program.          */

readbf()

        {
        int     s;

        if ( (s=Fread(boot_fd, (long)AOUT_LEN, &buffer[BOOT_START])) < 0 )
                {
                Cconws(boot_prg);
                Cconws(": cannot read file\r\n");
                exit(1);
                }
        else if ( s != AOUT_LEN )
                {
                Cconws(boot_prg);
                Cconws(": bad file format\r\n");
                }
        if ( (s=Fread(boot_fd, (long)(BOOT_SIZE+1), &buffer[BOOT_START])) < 0 )
                {
                Cconws(boot_prg);
                Cconws(": cannot read file\r\n");
                exit(1);
                }
        if ( s >= BOOT_SIZE+1 )         /* must be small enough to fit  */
                {                       /* in BOOT_SIZE bytes           */
                Cconws(boot_prg);
                Cconws(": boot program too long\r\n");
                exit(1);
                }
        }

/* format boot buffer */

fmtbb()

        {
        int     s;

        buffer[0]=0x60;                 /* bra *+28 opcode              */
        buffer[1]=0x1c;
        Protobt(buffer, -1L, -1, 1);    /* format boot buffer, do not   */
                                        /* change serial number, nor    */
                                        /* the disk type, but make boot */
        }                               /* sector executable            */
        
/* write the boot buffer onto disk boot sector */

writebs()

        {
        int     s;
        long    filler;

        if ( (s=Flopwr(buffer, filler, BOOT_DEV, BOOT_SECT, BOOT_TRK,
                BOOT_SIDE, NBOOT_SECT)) < 0 )
                {
                Cconws("mkboot: cannot write boot sector\r\n");
                exit(1);
                }
        }

/* close boot program file */

closebf()

        {
        Fclose(boot_fd);
        }

/* print usage and exit */

use_error()

        {
        Cconws("usage: mkboot [bootfile]\r\n");
        exit(1);
        }
