jim@byucsa.UUCP (10/30/83)
This is a repeat message, not sure if first one got out. We are looking for a boot block for a 750 with ra81 on uda50 running bsd4.1. Thanks for any and all help. jim (harpo!utah-cs!beesvax!byucsa!jim)
rbbb.rice%rand-relay@sri-unix.UUCP (11/04/83)
From: David Chase <rbbb.rice@rand-relay> Here is a (the?) boot program for a 750 with ra81 on uda50 running bsd4.1. It really works, or else I wouldn't be writing this. David Chase, Rice University ---------------------------------------------------------------- This is the boot block program to boot Unix from a UDA device. Actually, this is a general boot program, and can be used on any 750 with any devices, given that the appropriate boot ROMs are installed. It's been tested on UDAs and RK07s, but not yet on a MASSBUS device. Note that the CSR locations MUST be where the ROMs expect them; usual configurations have devices at non-standard locations. (eg, our UDA boot ROMs expect the CSR at 772150.) You often must change the hardwired CSR in sys/stand/uda.c as well, to make it conform. This program may be freely distributed but the opening comments MUST be left intact. ------------ /* * VAX 11-750 disk boot program to load "/boot" from * a UNIX filesystem into low core and to execute that file. * * This program can only read regular small 10k byte files * from the root of a UNIX filesystem. That is to say, it cannot * (does not care to) look at indirect blocks. It just loads * the (up to) first 10 blocks addressed by the direct map * pointers, and goes from there. * * If anything goes wrong during the boot, an error code is left in R7. * The codes are defined below. * * written by Scott Comer at the urging of Mike Caplinger. * copyright (c) LCSE, Rice University, Houston TX */ .set DATA, 0x3000 /* start of impure data area */ .set STACK, 0xfa00 /* good place for the stack */ .set BOOTBASE, 0xfe00 /* relocated home of boot block */ /* these three hold the register contents needed by the */ /* rom driver subroutine to access the boot device */ .set driver_r1, DATA .set driver_r2, driver_r1+4 .set driver_r3, driver_r2+4 .set driver, driver_r3+4 /* addr of driver routine */ .set inode_start, driver+4 .set di_mode, inode_start /* disk resident inode */ .set di_nlink, di_mode+2 .set di_uid, di_nlink+2 .set di_gid, di_uid+2 .set di_size, di_gid+2 .set di_addr, di_size+4 .set di_atime, di_addr+40 /* 13 map ptrs: 3 bytes each */ .set di_mtime, di_atime+4 .set di_ctime, di_mtime+4 .set inode_end, di_ctime+4 .set inode_size, inode_end-inode_start .set BLOCK_SIZE, 1024 /* file system block size */ .set inodes_per_block, BLOCK_SIZE/inode_size .set blocks_before_ilist, 2 /* boot and super blocks */ .set dir_size, 16 /* size of directory entry */ .set name_size, 14 /* size of name string */ .set ENTADR,024 /* offset to entry addr in a.out */ .set root_inode, 2 /* root dir inode no. */ .set NOT_FIRST_64K, 0x1001 .set UNSUPPORTED_DEVICE, 0x1002 .set RETURN_FROM_BOOT, 0x1003 .set COULD_NOT_FIND_BOOT, 0x1004 .set FILE_TOO_LARGE, 0x1005 .set FILE_READ_ERROR, 0x1006 init: .long 0 /* boot block parameters */ .long 0 /* (all unused, hence 0) */ .long 0 /* The registers are set by the console subsystem as follows. Those marked with stars are saved by the driver subroutine. Those marked with a "d" are used by the driver subroutine, and must contain the indicated values before calling the driver. r0 = type of boot device (see 750 hardware reference, console) ds r1 = address of the unibus i/o page ds r2 = boot device CSR address ds r3 = boot device unit number s r4 = ds r5 = software boot flags (driver: offset to buffer for read) s r6 = driver subroutine address r7 = d r8 = LBN of block to read from disk r9 = s r10 = s r11 = s ap = fp = s sp = Memory is mapped as follows: 0000 to 01ff Boot block program 0200 to f9ff Available fa00 to fdff Drivers and control routines fe00 to ffff Available The /boot programs are small (size <= 10240 bytes), and are ultimatly loaded starting at 0000. The UNIX boot block programs all assume this; hence I shall too. Because of this, the boot block program will have to relocate itself. Addresses above 27ff are available as scratch. Thus, the final layout of memory will be: 0000 to 27ff /boot program 2800 to f8ff Available for scratch f900 to f9ff Stack fa00 to fdff Drivers and control routines fe00 to ffff Boot block program (relocated) Upon calling the loaded program (/boot), the registers are expected to contain the following: r10 = boot device code (this is different from DEC codes; see table, later) r11 = software boot flags (from console boot command) */ start: clrl r7 movl r0, r10 /* save the device type */ moval init, r11 /* base address of good memory */ movl r5, ap /* save the boot flags */ tstl r11 /* see if it is zero */ beql 1f movzwl $NOT_FIRST_64K, r7 halt /* not in first 64k of memory */ 1: moval STACK(r11), sp /* put the stack somewhere good */ /* save the register contents needed by the boot driver */ movl r1, driver_r1(r11) movl r2, driver_r2(r11) movl r3, driver_r3(r11) movl r6, driver(r11) /* relocate the boot program */ movc3 $end, (r11), BOOTBASE(r11) jmp BOOTBASE+start2(r11) start2: /* running relocated */ pushl $root_inode /* go read the / directory */ calls $1, BOOTBASE+get_inode(r11) calls $0, BOOTBASE+read_file(r11) calls $0, BOOTBASE+search_boot(r11) /* look for 'boot' */ /* the inode number of 'boot' is now in r0 */ restart: pushl r0 /* read in 'boot' */ calls $1, BOOTBASE+get_inode(r11) calls $0, BOOTBASE+read_file(r11) /* if we make it thus far, boot has been loaded into */ /* memory starting at location 0. */ /* we still have to set up the registers as /boot will */ /* want them. After that, the program is called */ movl r11, r9 /* save the base pointer */ /* boot strap device codes from microcode routines */ .set AnyMassBus, 0 .set RK07, 1 .set RL02, 2 .set UDA50, 17 .set TU58, 64 cmpb r10, $AnyMassBus bneq 1f movzbl $0, r10 /* massbus disk */ brb 2f 1: cmpb r10, $RK07 bneq 1f movzbl $3, r10 /* rk07 disk */ brb 2f 1: cmpb r10, $UDA50 bneq 1f movzbl $9, r10 /* uda50 */ brb 2f 1: movzwl $UNSUPPORTED_DEVICE, r7 halt /* unsupported device */ 2: movl ap, r11 /* software boot flags */ addl3 di_size(r9), r9, r2 /* address to start clear */ moval BOOTBASE(r9), r1 /* address to stop clearing */ 1: cmpl r2, r1 bgeq 2f clrb (r2)+ brb 1b 2: calls $0, (r9) movzwl $RETURN_FROM_BOOT, r7 halt /* end of program */ boot_file: .byte 'b, 'o, 'o, 't, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 search_boot: .word 0xffc /* r11-r2 */ /* search the root directory for 'boot' */ /* returns the inode number in r0, or halts */ movl r11, r10 /* pointer to first directory entry */ addl3 di_size(r11), r11, r9 /* first byte past directory */ 1: tstw (r10) /* check the inode number */ beql 2f /* this entry is unused */ cmpc3 $name_size, BOOTBASE+boot_file(r11), 2(r10) /* check the name */ bneq 2f movzwl (r10), r0 /* found it, return the inumber */ ret 2: addl2 $dir_size, r10 /* continue the search with the */ cmpl r10, r9 /* gone past the end... */ blss 1b movzwl $COULD_NOT_FIND_BOOT, r7 halt /* could not find 'boot' */ read_file: .word 0xffc /* r11-r2 */ cmpl di_size(r11), $10240 /* no large files here */ bleq 1f movzwl $FILE_TOO_LARGE, r7 halt /* file too large */ 1: moval di_addr(r11), r2 clrl r3 2: extzv $0, $24, (r2), r4 beql 3f /* end of the list */ pushl r3 pushl r4 calls $2, BOOTBASE+read_block(r11) addl2 $3, r2 addl2 $BLOCK_SIZE, r3 brb 2b 3: ret read_block: .word 0xffc /* r11-r2 */ clrq -(sp) /* make room for the buf addr */ movl driver_r1(r11), r1 movl driver_r2(r11), r2 movl driver_r3(r11), r3 mull3 $2, 4(ap), r4 /* mult by 2 to get lbn */ movl r4, r8 movl 8(ap), r5 addl3 r5, r11, (sp) /* for massbus babies */ jsb *driver(r11) /* read the first block */ blbs r0, 1f movzwl $FILE_READ_ERROR, r7 halt /* error reading file */ 1: addl3 $1, r4, r8 addl2 $512, r5 addl3 r5, r11, (sp) /* for massbus babies */ jsb *driver(r11) /* read the second block */ blbs r0, 1f movzwl $FILE_READ_ERROR, r7 halt /* error reading file */ 1: ret get_inode: .word 0xffc /* r11-r2 */ /* turn into offset from beginning of disk */ /* (remember that inodes are numbered from 1?) */ addl3 $(inodes_per_block * blocks_before_ilist - 1), 4(ap), r0 clrl r1 ediv $inodes_per_block, r0, r0, r2 pushl $0 /* read into 0 */ pushl r0 calls $2, BOOTBASE+read_block(r11) /* read a block */ mull2 $inode_size, r2 addl2 r11, r2 movc3 $inode_size, (r2), inode_start(r11) ret end: ----------------------------------------------------------------