From: Jaakko Hyvatti (hyvatti@klaava.Helsinki.FI)
Date: 05/21/92


From: hyvatti@klaava.Helsinki.FI (Jaakko Hyvatti)
Subject: boothard.S - a bootsector for hard disks
Date: 21 May 1992 18:08:16 GMT


In article <gunter.706437336@severus> gunter@sci.kun.nl (Gunter Windau) writes:
>You might create a small partition on your harddisk that's just
>big enough to hold the linux bootimage and make this partition
>the 'active' one. I think the bios will load the kernel from this
>partition, just like it does from a floppy.
>I haven't tried it myself so it might not work, although I'd like
>to know if it does...

  It does not. What you need is a special bootsector for hard disks
like the one below. Be careful with it, I just got it working..

-- 
Jaakko Hyv{tti                          Jaakko.Hyvatti@Helsinki.FI
Lapinrinne 1 B 608                      hyvatti@plootu.helsinki.fi
00180  Helsinki, Finland                +358-0-6958 5368

================================================================== # # Makefile for boothard by Jaakko Hyv{tti 1992-05-21 # # Boothard.S is a hard disk boot sector designed to # be used for booting Linux from fixed disks. It does # the job of bootsect.S from original sources and is # a direct derivate of it. # # What you need is to make a bootable primary partition # for your kernel and kernel only. 256kB or 512kB # is enough for the Image file. # # Build your conventional linux kernel as usual # # Edit this Makefile to get LINUX and ROOT_DEV right # # Type 'make' in the directory where this Makefile and boothard.S # are. # # Then copy the resulting Image file to your newly created # hard disk partition, like 'cp Image /dev/hda4'. # # WARNING! Nobody but you is to blame if something breaks! # I am not reponsible for anything this piece # of garbage does! If you don't know what you are # doing do not do it. Back up everything. # # BUGS # # Somebody is free to document better the procedure of # getting this thing into use. # # Questions to Jaakko.Hyvatti@Helsinki.FI or hyvatti@cc.helsinki.fi

# # LINUX specifies where to find compiled kernel and include files #

LINUX = /usr/src/linux

# # ROOT_DEV specifies the default root-device when making the image. #

ROOT_DEV = /dev/hdb1

#

AS86 =as86 -0 -a LD86 =ld86 -0

CPP =/lib/cpp -nostdinc -I$(LINUX)/include

all: Image

Image: boothard $(LINUX)/boot/setup $(LINUX)/tools/system \ $(LINUX)/tools/build cp $(LINUX)/tools/system system.tmp strip system.tmp $(LINUX)/tools/build boothard $(LINUX)/boot/setup \ system.tmp $(ROOT_DEV) > Image rm system.tmp sync

boothard.s: boothard.S $(LINUX)/include/linux/config.h $(CPP) -traditional boothard.S -o boothard.s

boothard.o: boothard.s $(AS86) -o boothard.o boothard.s

boothard: boothard.o $(LD86) -s -o boothard boothard.o

clean: rm -f Image boothard boothard.o boothard.s

install: Image @echo @echo To install kernel to a bootable hard disk partition @echo just copy your Image file to it. @echo @echo WARNING! Doing so destroys all data on that partition! @echo @echo Example: @echo @echo cp Image /dev/hda4 @echo

# # end of Makefile for boothard # ================================================================= ! ! SYS_SIZE is the number of clicks (16 bytes) to be loaded. ! 0x4000 is 0x40000 bytes = 256kB, more than enough for current ! versions of linux ! #include <linux/config.h> SYSSIZE = DEF_SYSSIZE ! ! bootsect.S (C) 1991 Linus Torvalds ! modified by Drew Eckhardt ! modified by Bruce Evans (bde) ! modified by Jaakko J. Hyv{tti (jjh) to boot from hard disk. ! Original version was from Linux 0.96 sources. ! ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves ! itself out of the way to address 0x90000, and jumps there. ! ! bde - should not jump blindly, there may be systems with only 512K low ! memory. Use int 0x12 to get the top of memory, etc. ! ! It then loads 'setup' directly after itself (0x90200), and the system ! at 0x10000, using BIOS interrupts. ! ! NOTE! currently system is at most 8*65536 bytes long. This should be no ! problem, even in the future. I want to keep it simple. This 512 kB ! kernel size should be enough, especially as this doesn't contain the ! buffer cache as in minix ! ! The loader has been made as simple as possible, and continuos ! read errors will result in a unbreakable loop. Reboot by hand. It ! loads pretty fast by getting whole tracks at a time whenever possible.

.text

SETUPSECS = 4 ! nr of setup-sectors BOOTSEG = 0x07C0 ! original address of boot-sector INITSEG = DEF_INITSEG ! we move boot here - out of the way SETUPSEG = DEF_SETUPSEG ! setup starts here SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).

! ROOT_DEV & SWAP_DEV are now written by "build". ROOT_DEV = 0 SWAP_DEV = 0

! ld86 requires an entry symbol. This may as well be the usual one. .globl _main _main: #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ int 3 #endif push es ! jjh - es:bp is the location of the partition mov ax,#BOOTSEG ! table entry. Save it. mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di cld rep movsw jmpi go,INITSEG

go: mov ax,cs mov dx,#0x4000 ! 0x4000 is arbitrary value >= length of ! bootsect + length of setup + room for stack

! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We ! wouldn't have to worry about this if we checked the top of memory. Also ! my BIOS can be configured to put the wini drive tables in high memory ! instead of in the vector table. The old stack might have clobbered the ! drive table.

mov es,ax pop ds ! jjh - ds:bp is the partition table entry push ax

mov ss,ax ! put stack at INITSEG:0x4000. mov sp,dx

! Print some inane message

push bp mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#27 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 mov ax,#0x1301 ! write string, move cursor int 0x10 pop bp

! ok, we've written the message

mov ah,#8 ! read capacity mov si,bp mov dl,(si) ! drive number from partition table int 0x13 error1: jc error1 ! Who cares about errors?

and cl,#0x3f seg cs mov sectors,cl ! save the drive geometry inc dh seg cs mov heads,dh

mov si,bp ! get info from partition table mov dx,(si) ! drive and head mov cx,2(si) ! sector and track mov al,#1 call add_sectors ! skip the bootsector

mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPSECS ! service 2, nr of sectors int 0x13 ! read setup error2: jc error2 ! loop on error

! now we want to load the system (at 0x10000)

mov si,bp mov bp,#SYSSIZE ! maximum number of sectors needed to read shr bp,#5 cmp 0x0e(si),#0 ! check the size of the partition jnz load_it cmp bp,0x0c(si) jb load_it mov bp,0x0c(si) ! partition is smaller than SYSSIZE mov ax,#0xe20 ! tell it by printing a space int 0x10

load_it: mov ax,#SYSSEG mov es,ax ! segment of 0x010000 mov ax,cs mov ds,ax xor bx,bx ! loading offset 0 mov al,#SETUPSECS ! skip setup, it was just read

more: call add_sectors ! increment source sector mov ax,(sectors)

cmp bp,ax ! is there still more than one track? jb last_read sub bp,ax mov ax,#0xe2e ! yes, print a dot int 0x10 mov al,(sectors) mov ah,#2 int 0x13 ! load a track error3: jc error3 mov di,(sectors) ! increment destination segment shl di,#5 mov ax,es add ax,di mov es,ax mov al,(sectors) jmp more

last_read: mov ax,#0xe21 ! '!' int 0x10 mov ax,bp mov ah,#2 int 0x13 ! the rest of the last track error4: jc error4

call kill_motor ! just in case call print_nl

! After that we check which root-device to use. If the device is ! defined (!= 0), nothing is done and the given device is used. ! Otherwise halt, there is no point in checking out any floppies etc.

seg cs mov ax,root_dev or ax,ax undef_root: jz undef_root root_defined:

! after that (everything loaded), we jump to ! the setup-routine loaded directly after ! the bootblock:

jmpi 0,SETUPSEG

/* * jjh - This routine adds al to the sector-head-track number. * al must be <= (sectors) */

add_sectors: mov ah,cl and ah,#0x3f and cl,#0xc0 add al,ah cmp al,(sectors) jbe add1 sub al,(sectors) inc dh cmp dh,(heads) jb add1 sub dh,(heads) inc ch jnz add1 add cl,#0x40 add1: or cl,al ret

/* * This procedure turns off the floppy drive motor, so * that we enter the kernel in a known state, and * don't have to worry about it later. */ kill_motor: push dx mov dx,#0x3f2 xor al, al outb pop dx ret

print_nl: mov ax, #0xe0d ! CR int 0x10 mov al, #0xa ! LF int 0x10 ret

sectors: .word 0

heads: .word 0

msg1: .byte 13,10 .ascii "Welcome to the the jungle"

.org 506 swap_dev: .word SWAP_DEV root_dev: .word ROOT_DEV boot_flag: .word 0xAA55

! end of boothard.S