2 * This bootblock loads the linux-8086 executable in the file 'boot'
3 * from the root directory of a minix filesystem.
5 * Copyright (C) 1990-1998 Robert de Bath, distributed under the GPL Version 2
6 * Based on minix filesystem definitions.
9 * Alter nogood() to do a mov sp,... so the helper program can override
16 /* #define DOTS /* define to have dots printed */
17 /* #define HARDDISK /* Define for hard disk version */
18 /* #define TRY_FLOPPY /* To do trial reads to find floppy size */
20 /* #define MIN_SPACE */
22 #define zone_shift 0 /* for any < 32M (!= 0 not supported yet, if ever) */
23 #define seg_at(k) ((k)*64)
24 #define seg_of(p) ((unsigned int)p >>4)
25 #define BOOTSEG (0x07c0)
26 #define LOADSEG (0x1000)
27 #define ORGADDR (0x0500)
35 #define load_zone load_block
38 static short zone_shift
;
45 ! Apparently on startup the only things we can assume are that we start at
46 ! `start`
(ABS addr $
07C00
) and the boot sector is in the segment
.
48 ! So first set CS
=DS
=ES
=SS
=0
49 ! The we move
this to $
0500 and put the stack at the top of the first
64k
.
50 ! The directory
'file' is loaded $
1500 and scanned there
.
51 ! The final executable will be loaded in the
2nd
64k chunk
.
53 org ORGADDR
! The lowest available address
.
58 org start
! The lowest available address
, again
.
62 .ascii
"MINIXFS BOOT (C) 1990-1999, Robert de Bath"
67 ! A few variables we need to know the positions of
for patching
, so export
68 ! them
and as86_encaps will make some variables
. Put them here at the start
69 ! so they
're in the same place for both Floppy and harddisk versions as they
70 ! will be used by helper programs.
72 export inode ! Inode to search
74 _inode: .word 1 ! ROOT_INODE
77 export dinode ! Inode of directory file was found in.
79 _dinode: .word 1 ! ROOT_INODE
82 export bootfile ! File to boot, make this whatever you like,
83 bootfile: ! 'boot
' is good, 'linux
' too.
86 .byte 0,0,0,0,0,0,0,0,0,0
90 mov bx,[si+8] ! Fetch the linear address of part from DS:SI
91 mov dh,[si+10] ! DL is drive number
94 xor ax,ax ! All segments are zero, first 64k of mem.
102 mov ax,#$0203 ! Read 3 sectors, code + superblock.
103 mov bx,#start ! Where this _should_ be
104 mov cx,#$0001 ! From sector 1
105 xor dx,dx ! Of the floppy drive head zero
110 mov cx,#$100 ! Move 256 words
111 mov si,#BOOTADDR ! From default BB
112 mov di,#ORGADDR ! To the correct address.
117 mov [bootpart],bx ! Save the partition sector offset (and drive)
120 ! Read next 2 sectors of hd.
134 /****************************************************************************/
136 /****************************************************************************/
138 /* The name of the file and inode to start */
139 extern char bootfile[];
140 extern inode_nr inode;
141 extern inode_nr dinode;
143 /* For multi-sector reads */
144 extern sect_nr lastsect;
145 extern sect_nr firstsect;
146 extern unsigned loadaddr;
147 extern unsigned loadcount;
149 /* Keep track of zones to load */
150 extern zone_nr * next_zone;
151 extern zone_nr * end_zone;
152 extern zone_nr indirect;
154 /* Where to load zones */
155 extern unsigned ldaddr;
157 /* Directory reading */
158 extern dir_struct * dirptr;
159 extern unsigned flength;
160 extern unsigned dir_32;
163 /* The 'shape
' of the floppy - intuit from superblock or try to read max */
164 extern unsigned n_sectors;
167 extern struct super_block b_super;
168 extern d_inode b_inode[INODES_PER_BLOCK];
169 extern zone_nr b_zone[NR_INDIRECTS];
170 extern dir_struct directory[];
173 /****************************************************************************/
175 /****************************************************************************/
203 temp_space: .blkb 512
206 _directory: .blkb 32768
212 /****************************************************************************/
214 /****************************************************************************/
215 /* #if defined(HARDDISK) && !defined(SKIPBOOT) */
227 mov ah,#$E ! Can't use $
13 cause that
's AT+ only!
230 min_eos: ! Wait for a key then reboot
233 jmpi $0,$FFFF ! Reboot.
237 #if defined(HARDDISK)
238 .asciz "Initial boot failed, press return to reboot\r\n"
240 .asciz "Boot failed:"
250 /* This didn't work
, chain the boot sector of the HD */
255 mov ax
,#$0201 ! Read 1 sector
256 mov bx
,#BOOTADDR ! In the boot area
257 mov cx
,#$0001 ! From sector 1
258 mov dx
,#$0080 ! Of the hard drive head zero
260 jc hcode
! Keep trying forever
!
267 /****************************************************************************/
268 /* Section hd_sect */
269 /****************************************************************************/
273 ! Load AL sectors from linear sector DX
:CX into location ES
:BX
274 ! Linear sector zero is at
[bootpart
]
275 ! This loads one sector at a time
, but that
's OK cause even in the _very_
276 ! worst case it'll take no more that
5 seconds to load a
16 bit executable
.
292 push cx
! Drive
and sector
.
295 push es
! Load location
298 push cx
! Drive
and sector again
.
301 ! Fetch drive
'shape'
304 int $
13 ! DX
:CX
= drive specification
307 and cx
,#$3F ! Get sector count => DI
310 xor dl
,dl
! Get head count
=> SI
315 pop dx
! Get back drive
and sector
318 mov bl
,dh
! Save drive
321 div di
! DX
=sector
, AX
=track number
323 inc cl
! CL
=sector number
326 div si
! DX
=head
, AX
=cylinder
329 mov dl
,bl
! DX
for int 1302
334 or cx
,ax
! CX
for int 1302
336 pop bx
! ES
:BX
for int 1302
339 mov di
,#5 ! Lots of retries for a hd
345 xor ax
,ax
! Reset between each
try.
367 /****************************************************************************/
368 /* This is the end of the parts that MUST be in the first sector */
369 /* From here down the functions can safely be in any order. */
370 /****************************************************************************/
373 /****************************************************************************/
374 /* Section fd_block */
375 /****************************************************************************/
378 load_block(address
, blkno
)
379 unsigned address
, blkno
;
381 register sect_nr sectno
;
382 if(blkno
== 0) { zero_block(address
); return; }
387 sectno
= (sect_nr
)blkno
* 2;
388 load_sect(address
, sectno
);
389 load_sect(address
+32, sectno
+1);
393 /****************************************************************************/
395 /****************************************************************************/
400 bios_tabl
=temp_space
! Temp space
.
401 bios_disk
=temp_space
+4 !
403 bios_tabl
=dosfs_stat
! Temp space
.
404 bios_disk
=dosfs_stat
+4 !
407 #ifndef __CALLER_SAVES__
414 ! 0:bx is parameter table address
437 movb
4[di
],al
! patch sector count
442 #ifndef __CALLER_SAVES__
449 ! 0:0x78 is parameter table address
460 /****************************************************************************/
461 /* Section fd_get_now */
462 /****************************************************************************/
482 xor ax
,ax
! Bad
, retry
.
494 /****************************************************************************/
495 /* Section fd_probe */
496 /****************************************************************************/
500 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
502 ! These are the number of sectors per track that will be scanned
for.
503 ! For
3.5 inch floppies
36 is
2.88 Mb
, 18 is
1.44Mb
, 21 is
1.68Mb on
504 ! a
1.44Mb floppy drive
. 15 and 9 are
for 5.25 inch floppies
.
506 disksizes
: .byte
36,21,18,15,9
508 ! It seems that there is no BIOS call to get the number of sectors
. Guess
509 ! 36 sectors
if sector
36 can be read
, 18 sectors
if sector
18 can be read
,
510 ! 15 if sector
15 can be read
. Otherwise guess
9.
513 mov si
,#disksizes ! table of sizes to try
520 je got_sectors
! if all
else fails
, try 9
521 xchg ax
, cx
! cx
= track
and sector
522 xor dx
, dx
! drive
0, head
0
523 mov bx
,#probe_buf ! address after setup (es = cs)
524 mov ax
,#0x0201 ! service 2, 1 sector
526 jc probe_loop
! try next value
534 /* Guess the number of sectors based on the size of the file system */
535 if( (n_sectors
= b_super
.s_nzones
/ 40) > 11 ) n_sectors
/= 2;
540 /****************************************************************************/
541 /* Section fd_sect */
542 /****************************************************************************/
545 load_sect(address
, sectno
)
549 register sect_nr nsect
;
551 nsect
= sectno
%n_sectors
+1;
553 nsect
|= (sectno
<<8);
558 if( ( address
& 4095 ) && nsect
== lastsect
)
566 lastsect
= firstsect
= nsect
;
572 /****************************************************************************/
573 /* Section fd_zeroblk */
574 /****************************************************************************/
580 #if __FIRST_ARG_IN_AX__
597 /****************************************************************************/
598 /* Section hd_block */
599 /****************************************************************************/
601 /*----------------------------------*/
602 /* Hard disk block driver */
603 /*----------------------------------*/
609 #if __FIRST_ARG_IN_AX__
610 ! Fetch load location
613 ! Test
for block zero
616 ! Fetch load location
620 ! Test
for block zero
626 ! Iff block zero
, zap memory
661 /****************************************************************************/
663 /****************************************************************************/
672 /****************************************************************************/
673 /* Section prt_dots */
674 /****************************************************************************/
692 /****************************************************************************/
694 /****************************************************************************/
695 #if defined(HARDDISK) || !defined(MIN_SPACE)
699 if *>start+0x1FE ! Leave space for magic
703 fail! Part 1 too large!
709 /****************************************************************************/
710 /* Section prog_load */
711 /****************************************************************************/
718 if( b_super.s_magic == SUPER_MAGIC2 )
720 else if( b_super.s_magic == SUPER_MAGIC )
726 if( zone_shift != b_super.s_log_zone_size) nogood();
728 zone_shift = b_super.s_log_zone_size;
734 /* if( (n_sectors = b_super.s_nzones / 40) > 11 ) n_sectors /= 2; */
741 load_block(seg_of(b_inode), inode/INODES_PER_BLOCK
742 + b_super.s_imap_blocks
743 + b_super.s_zmap_blocks
747 ldaddr = LOADSEG; /* Load at 64k mark */
750 register d_inode * i_ptr;
751 i_ptr = b_inode + inode%INODES_PER_BLOCK;
752 next_zone = i_ptr->i_zone;
753 flength = i_ptr->i_size;
754 if( (i_ptr->i_mode & I_TYPE) == I_DIRECTORY )
756 ldaddr = seg_of(directory);
758 dinode = inode+1; /* Remember current directory */
760 inode = 0; /* Mark - we've no _file_ inode yet */
764 end_zone
= next_zone
+NR_DZONE_NUM
;
765 load_zone(seg_of(b_zone
), (indirect
= next_zone
[NR_DZONE_NUM
]));
770 if( next_zone
>= end_zone
)
775 end_zone
= next_zone
+ NR_INDIRECTS
;
781 load_zone(ldaddr
, *next_zone
);
783 ldaddr
+= (seg_at(1) << zone_shift
);
795 register char * s
= bootfile
;
796 register char * p
= dirptr
->d_name
;
806 inode
= dirptr
->d_inum
;
811 if( *s
++ != *p
++ ) break;
829 /****************************************************************************/
830 /* Section prog_run */
831 /****************************************************************************/
835 /* It all worked, run the loaded executable */
839 xchg dh
,dl
! DX
=> hard drive
840 push
[bootpart
] ! CX
=> partition offset
843 xor dx
,dx
! DX
=0 => floppy drive
844 push dx
! CX
=0 => partition offset
= 0
845 mov si
,[_n_sectors
] ! Save
for monitor
.out
849 mov ds
,bx
! DS
= loadaddress
852 cmp ax
,#0x0301 ! Right magic ?
853 jnz binfile
! Yuk
... assume
.SYS
855 inc bx
! bx
= initial CS
857 and ax
,#$20 ! Is it split I/D ?
866 mov sp
,[di
+24] ! Chmem value
871 push di
! jmpi
0,#LOADSEG+2
876 /****************************************************************************/
877 /* Section sys_libs */
878 /****************************************************************************/
880 ! These functions are pulled from the C library
.
885 mov ax
,dx
! instruction queue full so xchg slower
901 /****************************************************************************/
902 /* Section sys_vars */
903 /****************************************************************************/
925 /****************************************************************************/
927 /****************************************************************************/
931 fail
! Part
2 too large
!
934 if end_of_prog
<start
+0x201
943 /****************************************************************************/