static char SCCS_ID [] = "@(#)mkboot.c 1.7 17:17:52 - 82/06/30 "; /* * mkboot [-addr] file dev * * Copy as a bootstrappable program onto device at * block address (default 9600). * Set up sector 0 of the device to look like an OS/MT volume * descriptor for the LSU. * * Make a fake OS/MT directory and LIB prefix for the 3200-series LSU. */ #include #include #include /* only used in one place. see struct filsys below */ #include /* * OS/32 MT Structure definitions */ struct os_lib { /* OS/32 Loader Information Block */ char l_segt, /* segment type */ l_nlib, /* number of LIBs */ l_nlu, /* max number of logical units */ l_nasn, /* max number of assigns */ l_mpri, /* max priority */ l_ipri, /* initial priority */ l_preg, /* pure segmentation register */ l_ncom, /* number of task common segs */ l_nlsg, /* number of library segs */ l_tatr; /* task common attributes */ short l_opt; /* task options */ int l_segs, /* size of impure (sectors) */ l_fw2, /* num entries ?? */ l_fw3, /* max system space ?? */ l_itsw[2], /* initial TSW */ l_psiz, /* size of pure (sectors) */ l_prn, /* sector offset of pure */ l_segn; /* last word of segment name ?? */ char l_dumn[16]; /* dump file or dummy name ?? */ int l_his, /* patch history pointer */ l_fill0[4]; /* - */ char l_date[8], /* TET date */ l_time[8]; /* TET time */ short l_nioq, /* max queued I/O requests */ l_fill1; /* - */ int l_ctop, /* last halfword in partition */ l_utop; /* impure size (bytes) */ }; struct os_dir { /* OS/32 Directory Entry */ char d_fnm[8], /* file name */ d_ext[3], /* extension */ d_act; /* account */ int d_flba, /* first sector address */ d_llba; /* last sector address */ short d_keys, /* write/read keys */ d_lrcl; /* logical record length */ int d_date, /* date allocated */ d_luse; /* date last assigned */ short d_wcnt, /* write count */ d_rcnt; /* read count */ char d_atrb, /* attributes */ d_bksz, /* block size */ d_inbs, /* index block size */ d_mefx; /* mef number of extents ?? */ int d_csec, /* current sector or number of records */ d_pswd; /* password ?? */ }; struct os_dirblk { /* OS/32 Directory Block */ int db_next; /* sector address of next dirblk */ struct os_dir db_dir[5]; /* directory entries */ }; struct os_vd { /* OS/32 Volume Descriptor */ char v_vol[4]; /* volume name */ int v_atrb, /* attributes ?? */ v_fdp, /* sector address of first directory block */ v_osp, /* sector address of OS image */ v_oss, /* size of OS image (sectors) */ v_map, /* sector address of bit map */ v_ila, /* inverted list address ?? */ v_sdp; /* secondary directory pointer */ }; struct os_lib lib; struct os_dirblk dirblk; #define dir dirblk.db_dir[0] #define dir1 dirblk.db_dir[1] struct os_vd vd; #define SECSIZE 256 /* OS32 sector size */ #define pgtosec(x) ((x) * PGSIZE / SECSIZE) #define fsbtosec(x) ((x) * BSIZE / SECSIZE / CLSIZE) char buff[SECSIZE]; /* sector copy buffer */ long saddr = pgtosec(9600); /* sector address for bootstrap stuff */ int nsec; /* length (sectors) of bootstrap program */ main(argc, argv) char **argv; { register dev, file, len; register char *p; if (--argc && *(p = *++argv) == '-') { if ((saddr = pgtosec(atoi(++p))) <= 0) error("Illegal block number"); argc--; argv++; } if (argc < 2) error("Usage: mkboot [ - baddr ] file dev"); if ((file = open(*argv, 0)) < 0) error("Can't open %s", *argv); if ((dev = open(*++argv, 2)) < 0) error("Can't write on %s", *argv); /* * Make sure we aren't overwriting file system * NOTE: this assumes that there is a file system * at the beginning of the device we are going to write * on. Not always a valid assumption. */ lseek(dev, (long)BSIZE, 0); { struct filsys fs; if (read(dev, (char *) &fs, sizeof(fs)) != sizeof(fs)) error("Superblock read error"); } /* * Skip a.out header */ lseek(file, (long) sizeof (struct exec), 0); lseek(dev, (saddr+2) * SECSIZE, 0); /* * Copy file & count blocks copied */ while ((len = read(file, buff, SECSIZE)) > 0) { if (write(dev, buff, len) != len) error("Write error"); nsec++; } if (len < 0) error("Read error"); /* * Round up size to ensure that it's bigger than the LSU program * (to avoid P-E LSU relocation bug) */ if (nsec < 32) nsec = 32; /* * Set up a pseudo OS/MT volume descriptor for the LSU */ strncpy(vd.v_vol, "UNIX", 4); vd.v_fdp = saddr; vd.v_osp = saddr + 2; vd.v_oss = nsec; lseek(dev, 0L, 0); if (wrsec(dev, &vd, sizeof vd)) error("Volume label write error"); /* * Make directory block */ strncpy(dir.d_fnm, "BOOT ", 8); strncpy(dir.d_ext, " ", 3); dir.d_flba = saddr + 1; dir.d_llba = saddr + 1 + nsec + 1; dir.d_atrb = 0x13; dir.d_csec = nsec + 2; /* * Make directory entry 0 - needed for new lsu on * 832's puts in entry for OS32 */ strncpy(dir1.d_fnm, "OS32 ", 8); strncpy(dir1.d_ext, "000", 3); dir1.d_flba = saddr + 1; dir1.d_llba = saddr + 1 + nsec + 1; dir1.d_atrb = 0x13; dir1.d_csec = nsec + 2; lseek(dev, saddr * SECSIZE, 0); if (wrsec(dev, &dirblk, sizeof dirblk)) error("Directory block write error"); /* * Make loader information block */ lib.l_segt = 1; lib.l_nlib = 1; lib.l_nlu = 15; lib.l_mpri = lib.l_ipri = 128; lib.l_segs = nsec; lib.l_fw3 = 0xfffff; lib.l_itsw[1] = 0x60; lib.l_ctop = (nsec + 1) * SECSIZE - 2; lib.l_utop = nsec * SECSIZE; lseek(dev, (saddr+1) * SECSIZE, 0); if (wrsec(dev, &lib, sizeof lib)) error("Loader information block write error"); } /* * Write len bytes from addr to fd, null-padding to SECSIZE-byte sector */ wrsec(fd, addr, len) char *addr; { register n; static char zeroes[SECSIZE]; if (write(fd, addr, len) != len) return(1); if ((n = SECSIZE-len) > 0) if (write(fd, zeroes, n) != n) return(1); return(0); } error(s, x) { printf(s, x); printf("\n"); exit(1); }