Wednesday, March 12, 2014

[OSDI] Modifying bootsect.s on Linux v0.11 for Multi Booting Support

In Linux v0.11, the code for booting is written in X86 Assembly Code. It took me a little while understand the code and put some modification on it for the OSDI assignment.

In the assignment, we have to add a new bootable section in the floppy disk, and boot into that section. This part is described in the assignment document. Then, we have to enable the user to select which section he/she wants to boot, linux v0.11 or our new section (hello.s).

First we print out our custom message by calling "int $0x10", then read the insert key by calling "int $0x16". And, by looking up ASCII table, we check if the inserted code is '1' or '2' to boot the corresponding section.

Write "hello binary image" into Floppy Second Section

Modified tools/build.sh as below, so that we get our hello.s into the second section.
#!/bin/bash
# build.sh -- a shell version of build.c for the new bootsect.s & setup.s
# author: falcon <wuzhangjin@gmail.com>
# update: 2008-10-10

bootsect=$1
setup=$2
system=$3
IMAGE=$4
hello_img=$5    # [OSDI lab2]
root_dev=$6

# Set the biggest sys_size
# Changes from 0x20000 to 0x30000 by tigercn to avoid oversized code.
SYS_SIZE=$((0x3000*16))

# set the default "device" file for root image file
if [ -z "$root_dev" ]; then
        DEFAULT_MAJOR_ROOT=3
        DEFAULT_MINOR_ROOT=1
else
        DEFAULT_MAJOR_ROOT=${root_dev:0:2}
        DEFAULT_MINOR_ROOT=${root_dev:2:3}
fi

# Write bootsect (512 bytes, one sector) to stdout
[ ! -f "$bootsect" ] && echo "there is no bootsect binary file there" && exit -1
dd if=$bootsect bs=512 count=1 of=$IMAGE 2>&1 >/dev/null

# [OSDI lab2] add custom hello program
[ ! -f "$hello_img" ] && echo "there is no hello binary file there" && exit -1
dd if=$hello_img seek=1 bs=512 count=1 of=$IMAGE 2>&1 >/dev/null

# Write setup(4 * 512bytes, four sectors) to stdout
[ ! -f "$setup" ] && echo "there is no setup binary file there" && exit -1
dd if=$setup seek=2 bs=512 count=4 of=$IMAGE 2>&1 >/dev/null

# Write system(< SYS_SIZE) to stdout
[ ! -f "$system" ] && echo "there is no system binary file there" && exit -1
system_size=`wc -c $system |cut -d" " -f1`
[ $system_size -gt $SYS_SIZE ] && echo "the system binary is too big" && exit -1
dd if=$system seek=6 bs=512 count=$((2888-1-4)) of=$IMAGE 2>&1 >/dev/null

# Set "device" for the root image file
echo -ne "\x$DEFAULT_MINOR_ROOT\x$DEFAULT_MAJOR_ROOT" | dd ibs=1 obs=1 count=2 seek=508 of=$IMAGE conv=notrunc  2>&1 >/dev/null

Put Custom "hello.s" Section into the Directory

Yes, put "hello.s" under boot/. However, the hello.s I am using is not my work but the TA's, so it may not a good idea to put the code here.

Modify Makefile

Add the following things in boot/Makefile:
hello: hello.s
    @$(AS) -o hello.o hello.s
    @$(LD) $(LDFLAGS) -o hello hello.o
    @objcopy -R .pdr -R .comment -R.note -S -O binary hello

And, add the following things in ./Makefile:
Image: boot/bootsect boot/setup tools/system boot/hello
    @cp -f tools/system system.tmp
    @strip system.tmp
    @objcopy -O binary -R .note -R .comment system.tmp tools/kernel

    @tools/build.sh boot/bootsect boot/setup tools/kernel Image boot/hello $(ROOT_DEV)
    @rm system.tmp
    @rm tools/kernel -f
    @sync
boot/hello: boot/hello.s
    @make hello -C boot

Modify bootsect.s

And, here's the code I added in boot/bootsect.s:

# [OSDI lab2]: booting selection here
# print some message first
    mov     $0x03, %ah              # read cursor pos
    xor     %bh, %bh
    int     $0x10
    mov     $24, %cx
    mov     $0x0007, %bx            # page 0, attribute 7 (normal)
    mov     $msg2, %bp
    mov     $0x1301, %ax            # write string, move cursor
    int     $0x10
read_key:
    mov $0x0000, %ax
    int $0x16
    cmp $0x31, %al
    je load_setup
    cmp $0x32, %al
    je load_hello
    jmp read_key
# you can implement the load hello image code at here
load_hello:
    mov     $0x0000, %dx            # drive 0, head 0
    mov     $0x0002, %cx            # setup now change to sector 3, track 0 [OSDI lab2] editted
    mov     $0x0200, %bx            # address = 512, in INITSEG
    mov $0x0201, %ax                # service 2, nr of sectors
    int     $0x13                       # read it
    jnc     ok_load_hello           # ok - continue
    mov     $0x0000, %dx
    mov     $0x0000, %ax            # reset the diskette
    int     $0x13
    jmp     load_hello
ok_load_hello:
# Get disk drive parameters, specifically nr of sectors/track
    mov     $0x00, %dl
    mov     $0x0800, %ax            # AH=8 is get drive parameters
    int     $0x13
    mov     $0x00, %ch
    mov     %cx, %cs:sectors+0      # %cs means sectors is in %cs, [H]: not understanding
    mov     $SYSSEG, %ax
    mov     %ax, %es                # segment of 0x010000
    call    read_it
    call    kill_motor
# load the setup-sectors directly after the bootblock.
# Note that 'es' is already set up.
load_setup:

    ...

Reference

* thanks Schwannden Kuo for correcting my English