Refactored and reformatted.
Select default item at start. Added timeout handling. Don't switch to graphics mode, stay in text mode instead. Graphics mode led to display issues with lilo. Reverted order of text color like it is in original bootman. Fixed bugs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24933 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+500
-315
@@ -1,376 +1,561 @@
|
|||||||
;
|
;
|
||||||
; Copyright 2007, Dengg David, [email protected]. All rights reserved.
|
; Copyright 2007, Dengg David, [email protected]. All rights reserved.
|
||||||
|
; Copyright 2008, Michael Pfeiffer, [email protected]. All rights reserved.
|
||||||
|
; Copyright 2005, Ingo Weinhold, [email protected].
|
||||||
; Distributed under the terms of the MIT License.
|
; Distributed under the terms of the MIT License.
|
||||||
;
|
|
||||||
%assign BIOS_VIDEO_SERVICES 0x10
|
; Steps to create BootLoader.h
|
||||||
%assign BIOS_KEYBOARD_SERVICES 0x16
|
; 1. nasm -f bin bootman.S -o bootman.bin
|
||||||
%assign WRITE_CHAR 0x0e ; al - char
|
; 2. cc MakeArray.cpp -o make_array -lstdc++
|
||||||
|
; 3. ./make_array kBootLoader bootman.bin > BootLoader.h
|
||||||
|
; or
|
||||||
|
; nasm -f bin bootman.S -o bootman.bin && ./make_array kBootLoader bootman.bin > BootLoader.h
|
||||||
|
|
||||||
|
%assign USE_TEST_MENU 0
|
||||||
|
|
||||||
|
%assign BOOT_BLOCK_START_ADDRESS 0x7c00
|
||||||
|
|
||||||
|
%assign MBR_SIGNATURE 0xAA55
|
||||||
|
|
||||||
|
; BIOS calls
|
||||||
|
|
||||||
|
%assign BIOS_VIDEO_SERVICES 0x10
|
||||||
|
%assign BIOS_DISK_SERVICES 0x13
|
||||||
|
%assign BIOS_KEYBOARD_SERVICES 0x16
|
||||||
|
%assign BIOS_REBOOT 0x19
|
||||||
|
%assign BIOS_TIME_SERVICES 0x1A
|
||||||
|
|
||||||
|
; video services
|
||||||
|
%assign SET_VIDEO_MODE 0x00 ; al - mode
|
||||||
|
|
||||||
|
%assign SET_CURSOR 0x02 ; dl - column
|
||||||
|
; dh - row
|
||||||
|
; bh - page
|
||||||
|
|
||||||
|
|
||||||
|
%assign GET_CURSOR 0x03 ; bh - page
|
||||||
|
; -> dl - column
|
||||||
|
; dh - row
|
||||||
|
; Cursor shape:
|
||||||
|
; ch - starting scan line
|
||||||
|
; cl - ending scan line
|
||||||
|
|
||||||
|
%assign SCROLL_UP 0x06 ; al - lines (0: clear screen)
|
||||||
|
; bh - attribute
|
||||||
|
; ch - upper line
|
||||||
|
; cl - left column
|
||||||
|
; dh - lower line
|
||||||
|
; dl - right column
|
||||||
|
|
||||||
|
%assign WRITE_CHAR 0x09 ; al - char
|
||||||
|
; bh - page
|
||||||
|
; bl - attribute
|
||||||
|
; cx - count
|
||||||
|
|
||||||
|
;%assign WRITE_CHAR 0x0e ; al - char
|
||||||
; bh - page
|
; bh - page
|
||||||
; bl - foreground color (graphics mode only)
|
; bl - foreground color (graphics mode only)
|
||||||
|
|
||||||
[bits 16] ; Real Mode yeah
|
; disk services
|
||||||
start:
|
%assign READ_DISK_SECTORS 0x02 ; dl - drive
|
||||||
; ======================= SCREEN SETUP =================================
|
; es:bx - buffer
|
||||||
mov ax, 0x07C0 ; Segment Location 0x07C0
|
; dh - head (0 - 15)
|
||||||
mov ds, ax ; Set Data Segment to 0x07C0
|
; ch - track 7:0 (0 - 1023)
|
||||||
mov es, ax ; Set Extra Segment to 0x07C0
|
; cl - track 9:8,
|
||||||
mov ss, ax ; Set Stack Segment to 0x07C0
|
; sector (1 - 17)
|
||||||
mov sp, 0xFFFF
|
; al - sector count
|
||||||
|
; -> al - sectors read
|
||||||
|
%assign READ_DRIVE_PARAMETERS 0x08 ; dl - drive
|
||||||
|
; -> cl - max cylinder 9:8
|
||||||
|
; - sectors per track
|
||||||
|
; ch - max cylinder 7:0
|
||||||
|
; dh - max head
|
||||||
|
; dl - number of drives (?)
|
||||||
|
%assign CHECK_DISK_EXTENSIONS_PRESENT 0x41 ; bx - 0x55aa
|
||||||
|
; dl - drive
|
||||||
|
; -> success: carry clear
|
||||||
|
; ah - extension version
|
||||||
|
; bx - 0xaa55
|
||||||
|
; cx - support bit mask
|
||||||
|
; -> error: carry set
|
||||||
|
%assign EXTENDED_READ 0x42 ; dl - drive
|
||||||
|
; ds:si - address packet
|
||||||
|
; -> success: carry clear
|
||||||
|
; -> error: carry set
|
||||||
|
|
||||||
mov ah, 0x00 ; Set Screen Resolution to 640x480
|
%assign FIXED_DISK_SUPPORT 0x1 ; flag indicating fixed disk
|
||||||
mov al, 0x12
|
; extension command subset
|
||||||
mov bx, 0x0
|
|
||||||
mov cx, 0x1
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
mov ah, 0x02 ; Set cursor position
|
; keyboard services
|
||||||
mov dx, 0x0120
|
%assign READ_CHAR 0x00 ; -> al - ASCII char
|
||||||
int 0x10
|
; ah - scan code
|
||||||
|
|
||||||
|
%assign PROBE_CHAR 0x01 ; -> zf = 0
|
||||||
|
; al - ASCII char
|
||||||
|
; ah - scan code
|
||||||
|
; timer services
|
||||||
|
%assign READ_CLOCK 0x00 ; -> cx - high word
|
||||||
|
; dx - low word
|
||||||
|
; one tick = 1/18.2s
|
||||||
|
|
||||||
|
%assign TICKS_PER_SECOND 19
|
||||||
|
|
||||||
|
; video modes
|
||||||
|
%assign GRAPHIC_MODE_80x25 0x12 ; 640 x 480 graphic mode
|
||||||
|
|
||||||
|
%assign TEXT_COLUMNS 80 ; Number of columns
|
||||||
|
%assign TEXT_ROWS 25 ; Number of rows
|
||||||
|
|
||||||
|
; Colors
|
||||||
|
%assign BLACK 0
|
||||||
|
%assign BLUE 1
|
||||||
|
%assign GREEN 2
|
||||||
|
%assign CYAN 3
|
||||||
|
%assign RED 4
|
||||||
|
%assign MAGENTA 5
|
||||||
|
%assign BROWN 6
|
||||||
|
%assign LIGHT_GRAY 7
|
||||||
|
%assign DARK_GRAY 8
|
||||||
|
%assign LIGHT_BLUE 9
|
||||||
|
%assign LIGHT_GREEN 10
|
||||||
|
%assign LIGHT_CYAN 11
|
||||||
|
%assign LIGHT_RED 12
|
||||||
|
%assign LIGHT_MAGENTA 13
|
||||||
|
%assign YELLOW 14
|
||||||
|
%assign WHITE 15
|
||||||
|
|
||||||
|
%assign BRIGHT_COLOR_MASK 8
|
||||||
|
|
||||||
|
|
||||||
mov si, signation ; Print "Haiku Bootmanager"
|
; Key codes
|
||||||
call printstr
|
%assign KEY_DOWN 0x50
|
||||||
|
%assign KEY_UP 0x48
|
||||||
|
%assign KEY_RETURN 0x1C
|
||||||
|
|
||||||
|
; String constants with their length
|
||||||
|
%define TITLE 'Haiku Boot Manager'
|
||||||
|
%strlen TITLE_LENGTH TITLE
|
||||||
|
%define SELECT_OS_MESSAGE 'Select an OS from the menu'
|
||||||
|
%strlen SELECT_OS_MESSAGE_LENGTH SELECT_OS_MESSAGE
|
||||||
|
|
||||||
|
; 16 bit code
|
||||||
|
SECTION
|
||||||
|
BITS 16
|
||||||
|
|
||||||
|
|
||||||
mov ah, 0x02 ; Set cursor position
|
; nicer way to get the size of a structure
|
||||||
mov dx, 0x1B1B
|
%define sizeof(s) s %+ _size
|
||||||
int 0x10
|
|
||||||
|
|
||||||
mov si, select_os ; Print "Select Os..."
|
; using a structure in a another structure definition
|
||||||
call printstr
|
%macro nstruc 1-2 1
|
||||||
|
resb sizeof(%1) * %2
|
||||||
|
%endmacro
|
||||||
|
|
||||||
mov ah, 0
|
%macro DEBUG_PAUSE 0
|
||||||
int 0x16
|
push ax
|
||||||
|
mov ah, READ_CHAR
|
||||||
|
int BIOS_KEYBOARD_SERVICES
|
||||||
|
pop ax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
; ======================= LOAD 3 MORE SECTORS INTO MEM =================
|
%macro clearScreen 0
|
||||||
load_from_disk: ; load 3 more sectors into mem
|
mov ah, SCROLL_UP
|
||||||
mov ah, 0x42
|
xor al, al
|
||||||
mov dl, 0x80
|
mov bh, WHITE
|
||||||
mov si, DAP
|
xor cx, cx
|
||||||
int 0x13
|
mov dx, (TEXT_ROWS-1) * 0x100 + (TEXT_COLUMNS-1)
|
||||||
mov si, error
|
int BIOS_VIDEO_SERVICES
|
||||||
jc printstr
|
%endmacro
|
||||||
jmp secsec ; Jump into the second sector
|
|
||||||
|
|
||||||
ende:
|
; Prints a null terminated string
|
||||||
mov ah, 0x0e
|
; si ... offset to string
|
||||||
mov al, 'F'
|
%macro printString 0
|
||||||
mov bx, 0x2
|
push cx
|
||||||
mov cx, 0x1
|
jmp .loop_condition
|
||||||
int 0x10
|
|
||||||
jmp $ ; Final Loopy. Never reached
|
|
||||||
|
|
||||||
%if 0
|
|
||||||
printstr: ; Poor mans printf
|
|
||||||
lodsb
|
|
||||||
mov ah, 0x0E
|
|
||||||
mov bx, 0x0F
|
|
||||||
mov cx, 0x01
|
|
||||||
int 0x10
|
|
||||||
cmp al, 0x00
|
|
||||||
jnz printstr
|
|
||||||
ret
|
|
||||||
%else
|
|
||||||
printstr:
|
|
||||||
; page and foreground color
|
|
||||||
jmp .loop_condition
|
|
||||||
.loop
|
.loop
|
||||||
mov ah, WRITE_CHAR
|
mov cx, 1
|
||||||
mov bx, 0x0F
|
mov ah, WRITE_CHAR
|
||||||
mov cx, 1
|
int BIOS_VIDEO_SERVICES
|
||||||
int BIOS_VIDEO_SERVICES
|
mov ah, GET_CURSOR
|
||||||
.loop_condition
|
int BIOS_VIDEO_SERVICES
|
||||||
|
inc dl
|
||||||
|
mov ah, SET_CURSOR
|
||||||
|
int BIOS_VIDEO_SERVICES
|
||||||
|
.loop_condition
|
||||||
lodsb
|
lodsb
|
||||||
cmp al, 0
|
cmp al, 0
|
||||||
jnz .loop
|
jnz .loop
|
||||||
|
pop cx
|
||||||
ret
|
ret
|
||||||
%endif
|
%endmacro
|
||||||
|
|
||||||
DAP:
|
|
||||||
db 0x10 ; Size of DAP
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
db 0x03 ; number of sectors to read
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
dw 0x0200 ; segment:offset pointer to buffer
|
|
||||||
dw 0x07C0 ; segment:offset pointer to buffer
|
|
||||||
dw 0x0001 ; LBA address
|
|
||||||
dw 0x0000
|
|
||||||
dw 0x0000
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
WinDAP:
|
|
||||||
db 0x0B ; Size of DAP
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
db 0x01 ; number of sectors to read
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
dw 0x0000 ; segment:offset pointer to buffer
|
|
||||||
dw 0x07C0 ; segment:offset pointer to buffer
|
|
||||||
dw 0x003F ; LBA address
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
|
; 64 bit value
|
||||||
|
struc quadword
|
||||||
|
.lower resd 1
|
||||||
|
.upper resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
signation:
|
; address packet as required by the EXTENDED_READ BIOS call
|
||||||
db 'Haiku Bootmanager', 0x00
|
struc AddressPacket
|
||||||
select_os:
|
.packet_size resb 1
|
||||||
db 'Select an OS from the menu', 0x00
|
.reserved1 resb 1
|
||||||
|
.block_count resb 1
|
||||||
|
.reserved2 resb 1
|
||||||
|
.buffer resd 1
|
||||||
|
.offset nstruc quadword
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
; use code available in stage 1
|
||||||
|
%define printstr printStringStage1
|
||||||
|
|
||||||
|
stage1:
|
||||||
|
mov ax, 0x07C0 ; BOOT_BLOCK_START_ADDRESS / 16
|
||||||
|
mov ds, ax ; Setup segment registers
|
||||||
|
mov es, ax
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
times 510 -($-$$) db 'B' ; Fill the missing space to reach 510 byte and set the
|
mov sp, 0xFFFF ; Make stack empty
|
||||||
dw 0xAA55 ; magic marker "AA55" (to identify a valid bootrecord)
|
|
||||||
|
cld ; String operations increment index registers
|
||||||
|
|
||||||
|
clearScreen
|
||||||
|
|
||||||
|
mov bh, 0 ; Text output on page 0
|
||||||
|
|
||||||
|
; Print title centered at row 2
|
||||||
|
mov ah, SET_CURSOR
|
||||||
|
mov dx, 1 * 0x100 + (40 - TITLE_LENGTH / 2)
|
||||||
|
int BIOS_VIDEO_SERVICES
|
||||||
|
|
||||||
|
mov si, kTitle
|
||||||
|
mov bl, WHITE
|
||||||
|
call printstr
|
||||||
|
|
||||||
|
; Print message centered at second last row
|
||||||
|
mov ah, SET_CURSOR
|
||||||
|
mov dx, (TEXT_ROWS-2) * 0x100 + (40 - SELECT_OS_MESSAGE_LENGTH / 2)
|
||||||
|
mov bl, LIGHT_GRAY
|
||||||
|
int BIOS_VIDEO_SERVICES
|
||||||
|
|
||||||
|
mov si, kSelectOSMessage
|
||||||
|
call printstr
|
||||||
|
|
||||||
|
; Chain load rest of boot loader
|
||||||
|
mov ah, EXTENDED_READ ; Load 3 more sectors
|
||||||
|
mov dl, 0x80 ; First HDD
|
||||||
|
mov si, nextStageDAP
|
||||||
|
int BIOS_DISK_SERVICES
|
||||||
|
jc .error ; I/O error
|
||||||
|
jmp stage2 ; Continue in loaded stage 2
|
||||||
|
|
||||||
|
.error:
|
||||||
|
mov si, kError
|
||||||
|
mov bl, RED
|
||||||
|
call printstr
|
||||||
|
.halt
|
||||||
|
mov ah, READ_CHAR
|
||||||
|
int BIOS_KEYBOARD_SERVICES
|
||||||
|
hlt
|
||||||
|
jmp .halt
|
||||||
|
|
||||||
|
printStringStage1:
|
||||||
|
printString
|
||||||
|
|
||||||
|
nextStageDAP:
|
||||||
|
istruc AddressPacket
|
||||||
|
at AddressPacket.packet_size, db 0x10
|
||||||
|
at AddressPacket.block_count, db 0x03
|
||||||
|
at AddressPacket.buffer, dw 0x0200, 0x07c0
|
||||||
|
at AddressPacket.offset, dw 1
|
||||||
|
iend
|
||||||
|
|
||||||
|
kTitle:
|
||||||
|
db TITLE, 0x00
|
||||||
|
kSelectOSMessage:
|
||||||
|
db SELECT_OS_MESSAGE, 0x00
|
||||||
|
kError:
|
||||||
|
db 'Error loading sectors!', 0x00
|
||||||
|
|
||||||
|
; Fill the missing space to reach 510 byte
|
||||||
|
times 510 -($-$$) db 'B'
|
||||||
|
|
||||||
|
signature:
|
||||||
|
; Magic marker "AA55" (to identify a valid boot record)
|
||||||
|
dw MBR_SIGNATURE
|
||||||
|
|
||||||
; ======================================================================
|
; ======================================================================
|
||||||
; ======================= SECOND SECTOR ================================
|
; ======================= SECOND SECTOR ================================
|
||||||
; ======================================================================
|
; ======================================================================
|
||||||
|
|
||||||
secsec:
|
; Use code available in stage 1
|
||||||
; ======================= Center list ==================================
|
%define printstr printStringStage2
|
||||||
xor bx,bx ; Get ready for the Division
|
|
||||||
xor ax, ax ; Get ready for the Division
|
|
||||||
mov al, [list_items]
|
|
||||||
mov bl, 2 ; Divide by two
|
|
||||||
div bl ; Divide
|
|
||||||
|
|
||||||
mov bl, 12
|
%assign TIMEOUT_OFF 0xffff
|
||||||
sub bl, al ; Substract from 12 (screen is 80x25)
|
|
||||||
mov dh, bl
|
|
||||||
mov [first_position], dx
|
|
||||||
|
|
||||||
; ======================= Print the OS list ============================
|
|
||||||
print_list:
|
|
||||||
mov dx, [first_position]
|
|
||||||
mov [position], dx
|
|
||||||
|
|
||||||
mov ah, 0x02 ; Set cursor position
|
stage2:
|
||||||
int 0x10
|
mov ax, [defaultItem] ; Select default item
|
||||||
mov si, list ; Load the List
|
mov [selection], ax
|
||||||
xor cx,cx ; Load listitems to CX
|
|
||||||
mov byte [colour], 0x0000 ; Reset Colour
|
|
||||||
print_list_loop:
|
|
||||||
lodsb ; Get lenght of string from list into al
|
|
||||||
; Get the Text to be in the middle (40 - lenght/2)
|
|
||||||
xor bx,bx ; Get ready for the Division
|
|
||||||
mov ah, 0x00
|
|
||||||
mov bl, 2 ; Divide by two
|
|
||||||
div bl ; Divide
|
|
||||||
|
|
||||||
mov bl, 40
|
|
||||||
sub bl, al ; Substract from 40 (screen is 80x25)
|
|
||||||
mov al, bl
|
|
||||||
mov dx, [position] ; Get last position
|
|
||||||
inc dh ; Next line
|
|
||||||
mov dl, al ; Move it to the place where the row should be for the interrupt (DL)
|
|
||||||
|
|
||||||
mov ah, 0x02 ; Set cursor position
|
mov ax, TICKS_PER_SECOND ; Calculate timeout ticks
|
||||||
mov [position], dx
|
mul word [timeout]
|
||||||
int 0x10
|
mov bx, dx
|
||||||
|
push ax
|
||||||
|
|
||||||
mov dx, [selection]
|
mov ah, READ_CLOCK
|
||||||
mov byte bl, [colour] ; Load Colour
|
int BIOS_TIME_SERVICES
|
||||||
and bx, 0x03 ; Just
|
|
||||||
inc bl ; Colours ... 1-4
|
pop ax ; Add current ticks
|
||||||
cmp cx, [selection]
|
add ax, dx
|
||||||
jnz no_highlight
|
adc bx, cx
|
||||||
xor bx, 0x08 ; Highlight selected item
|
mov [timeoutTicks], ax
|
||||||
no_highlight:
|
mov [timeoutTicks + 2], bx
|
||||||
mov byte [colour], bl ; Store Colour
|
|
||||||
call print_list_item
|
mov al, [listItemCount] ; Calculate start row for menu
|
||||||
inc cx
|
shr al, 1
|
||||||
cmp cx, [list_items]
|
mov bl, TEXT_ROWS / 2
|
||||||
jne print_list_loop
|
sub bl, al ; y = TEXT_ROWS / 2 - number of items / 2
|
||||||
|
mov [firstLine], bl
|
||||||
|
|
||||||
|
call printMenu
|
||||||
|
|
||||||
|
cmp word [timeout], TIMEOUT_OFF
|
||||||
|
je inputLoop
|
||||||
|
|
||||||
|
timeoutLoop:
|
||||||
|
mov ah, PROBE_CHAR
|
||||||
|
int BIOS_KEYBOARD_SERVICES
|
||||||
|
jnz inputLoop ; cancel timeout if key is pressed
|
||||||
|
call isTimeoutReached
|
||||||
|
jnc timeoutLoop
|
||||||
|
jmp bootSelectedPartition
|
||||||
|
|
||||||
|
isTimeoutReached:
|
||||||
|
mov ah, READ_CLOCK
|
||||||
|
int BIOS_TIME_SERVICES
|
||||||
|
cmp cx, [timeoutTicks + 2]
|
||||||
|
jb .returnFalse
|
||||||
|
ja .returnTrue
|
||||||
|
cmp dx, [timeoutTicks]
|
||||||
|
ja .returnTrue
|
||||||
|
.returnFalse:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
.returnTrue:
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
|
||||||
; ================== Wait for a key and do something with it ==================
|
; ================== Wait for a key and do something with it ==================
|
||||||
|
mainLoop:
|
||||||
|
call printMenu
|
||||||
|
|
||||||
|
inputLoop:
|
||||||
|
mov ah, READ_CHAR
|
||||||
|
int BIOS_KEYBOARD_SERVICES ; AL = ASCII Code, AH = Scancode
|
||||||
|
|
||||||
main_loopy:
|
cmp ah, KEY_DOWN
|
||||||
mov ah, 0x02 ; Set cursor position
|
je selectNextPartition
|
||||||
mov dx, 0x181C
|
|
||||||
int 0x10
|
cmp ah, KEY_UP
|
||||||
|
je selectPreviousPartition
|
||||||
mov ah, 0x00 ; Keyboard Read: wait for key
|
|
||||||
int 0x16 ; AL = ASCII Code, AH = Scancode
|
cmp ah, KEY_RETURN
|
||||||
cmp ah, 0x50
|
je bootSelectedPartition
|
||||||
jz key_down ; Was it key_down, key_up... ?
|
|
||||||
cmp ah, 0x48
|
jmp inputLoop
|
||||||
jz key_up
|
|
||||||
cmp ah, 0x1C
|
|
||||||
jz key_enter
|
|
||||||
|
|
||||||
jmp main_loopy
|
selectNextPartition:
|
||||||
|
mov ax, [selection]
|
||||||
|
inc ax
|
||||||
|
cmp ax, [listItemCount]
|
||||||
|
jne .done ; At end of list?
|
||||||
|
xor ax, ax ; Then jump to first entry
|
||||||
|
.done:
|
||||||
|
mov [selection], ax
|
||||||
|
jmp mainLoop
|
||||||
|
|
||||||
|
selectPreviousPartition:
|
||||||
|
mov ax, [selection]
|
||||||
|
or ax, ax
|
||||||
|
jnz .done ; At top of list?
|
||||||
|
mov ax, [listItemCount] ; Then jump to last entry
|
||||||
|
.done:
|
||||||
|
dec ax
|
||||||
|
mov [selection], ax
|
||||||
|
jmp mainLoop
|
||||||
|
|
||||||
key_down:
|
|
||||||
mov ax, [selection]
|
; ======================= Print the OS list ============================
|
||||||
mov bx, [list_items]
|
printMenu:
|
||||||
dec bx
|
mov al, [firstLine]
|
||||||
cmp ax, bx
|
mov [currentLine], al
|
||||||
je key_down_no ; Are we at the bottom of the list?
|
|
||||||
inc ax
|
mov si, list ; Start at top of list
|
||||||
mov [selection], ax
|
xor cx, cx ; The index of the current item
|
||||||
key_down_no:
|
|
||||||
jmp print_list
|
.loop:
|
||||||
key_up:
|
lodsb ; String length incl. 0-terminator
|
||||||
mov ax, [selection]
|
dec al ; center menu item
|
||||||
mov bx, [list_items]
|
shr al, 1 ; x = TEXT_COLUMNS / 2 - length / 2
|
||||||
cmp ax, 0
|
mov dl, TEXT_COLUMNS / 2
|
||||||
je key_down_no ; Are we at the top of the list?
|
sub dl, al
|
||||||
dec ax
|
|
||||||
mov [selection], ax
|
mov dh, [currentLine]
|
||||||
key_up_no:
|
mov ah, SET_CURSOR
|
||||||
jmp print_list
|
int BIOS_VIDEO_SERVICES
|
||||||
|
|
||||||
|
mov di, cx
|
||||||
|
and di, 3
|
||||||
|
mov bl, [kColorTable + di] ; Text color
|
||||||
|
|
||||||
|
cmp cx, [selection]
|
||||||
|
jne .print ; Selected item reached?
|
||||||
|
xor bl, BRIGHT_COLOR_MASK ; Highlight it
|
||||||
|
|
||||||
|
.print:
|
||||||
|
call printstr
|
||||||
|
add si, sizeof(quadword) ; Skip start sector quad word
|
||||||
|
|
||||||
|
inc byte [currentLine]
|
||||||
|
inc cx
|
||||||
|
|
||||||
|
cmp cx, [listItemCount]
|
||||||
|
jne .loop
|
||||||
|
|
||||||
|
mov ah, SET_CURSOR ; Set cursor position
|
||||||
|
mov dx, (TEXT_ROWS-4) * 0x100 + (TEXT_COLUMNS / 3)
|
||||||
|
mov dx, 0x181C
|
||||||
|
int BIOS_VIDEO_SERVICES
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
; ========================== Chainload ==========================
|
; ========================== Chainload ==========================
|
||||||
|
|
||||||
key_enter:
|
bootSelectedPartition:
|
||||||
mov cx, [selection]
|
|
||||||
mov si, list
|
mov si, list ; Search address of start sector
|
||||||
inc cx
|
; of the selected item.
|
||||||
load_LBA:
|
mov cx, [selection]
|
||||||
lodsb
|
inc cx ; Number of required iterations
|
||||||
cmp al, 0x80
|
|
||||||
jne load_LBA
|
|
||||||
loop load_LBA
|
|
||||||
|
|
||||||
|
xor ah, ah ; The high-byte of the string length
|
||||||
|
; see loop body
|
||||||
|
jmp .search_loop_entry
|
||||||
|
|
||||||
|
.search_loop:
|
||||||
|
add si, sizeof(quadword) ; Skip to begin of next menu item
|
||||||
|
|
||||||
|
.search_loop_entry:
|
||||||
|
lodsb ; Length of menu item name
|
||||||
|
add si, ax ; Skip name to address of start sector
|
||||||
|
loop .search_loop
|
||||||
|
|
||||||
|
mov di, bootSectorDAP+AddressPacket.offset ; Copy start sector
|
||||||
|
mov cx, 4 ; It is stored in a quad word
|
||||||
|
.copy_start_sector
|
||||||
lodsw
|
lodsw
|
||||||
mov [LBA_selectionA], ax
|
stosw
|
||||||
lodsw
|
loop .copy_start_sector
|
||||||
mov [LBA_selectionB], ax
|
|
||||||
|
mov ah, EXTENDED_READ ; Now read start sector from HD
|
||||||
|
mov dl, 0x80 ; overwriting our first stage
|
||||||
|
mov si, bootSectorDAP
|
||||||
|
int BIOS_DISK_SERVICES
|
||||||
|
mov si, kReadError
|
||||||
|
jc printAndHalt ; Failed to read sector
|
||||||
|
|
||||||
|
mov ax, [signature]
|
||||||
|
cmp ax, MBR_SIGNATURE
|
||||||
|
mov si, kNoBootablePartitionError
|
||||||
|
jne printAndHalt ; Missing signature
|
||||||
|
|
||||||
mov si, ChainLoad_DAP ; Load the List
|
jmp $$ ; Start loaded boot loader
|
||||||
mov ax, [LBA_selectionA]
|
|
||||||
mov word [si+8], ax
|
|
||||||
mov ax, [LBA_selectionB]
|
|
||||||
mov word [si+10], ax
|
|
||||||
|
|
||||||
mov ah, 0x42
|
|
||||||
mov dl, 0x80
|
|
||||||
mov si, ChainLoad_DAP
|
|
||||||
int 0x13
|
|
||||||
mov si, error_lfd
|
|
||||||
jc print_debug
|
|
||||||
|
|
||||||
mov si, 0x0
|
|
||||||
xor ax, ax
|
|
||||||
mov si, error_nb
|
|
||||||
mov byte al, [0x01FE]
|
|
||||||
cmp al, 0x55
|
|
||||||
jne print_debug
|
|
||||||
|
|
||||||
mov byte al, [0x01FF]
|
|
||||||
cmp al, 0xAA
|
|
||||||
jne print_debug
|
|
||||||
|
|
||||||
mov si, yeah ; Yeah
|
|
||||||
jmp print_debug
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ====================== THE printMenu function ================
|
||||||
|
|
||||||
fin:
|
printStringStage2:
|
||||||
mov ah, 0x0e
|
printString
|
||||||
mov al, 'F'
|
|
||||||
mov bx, 0x2
|
|
||||||
mov cx, 0x1
|
|
||||||
int 0x10
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
|
printAndHalt:
|
||||||
; ====================== THE print_list function ================
|
mov bx, 0x0F ; Page number and foreground color
|
||||||
|
call printstr
|
||||||
print_list_item:
|
.halt
|
||||||
print_list_item_loop:
|
mov ah, READ_CHAR
|
||||||
lodsb
|
int BIOS_KEYBOARD_SERVICES
|
||||||
cmp al,0x80
|
hlt
|
||||||
jz print_list_item_end
|
jmp .halt
|
||||||
mov ah, 0x0E
|
|
||||||
int 0x10
|
|
||||||
jmp print_list_item_loop
|
|
||||||
print_list_item_end:
|
|
||||||
lodsw
|
|
||||||
lodsw
|
|
||||||
ret
|
|
||||||
|
|
||||||
print_debug: ; Poor mans printf again
|
|
||||||
lodsb
|
|
||||||
mov ah, 0x0E
|
|
||||||
mov bx, 0x0F
|
|
||||||
mov cx, 0x01
|
|
||||||
int 0x10
|
|
||||||
cmp al, 0x00
|
|
||||||
jnz print_debug
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
; ================================ DATA ===========================
|
; ================================ DATA ===========================
|
||||||
|
|
||||||
error_lfd:
|
selection:
|
||||||
db 'Error loading Sectors', 0x00
|
dw 0x0000
|
||||||
error_nb:
|
firstLine:
|
||||||
db 'Not a bootable partition', 0x00
|
db 0
|
||||||
LBA_selectionA:
|
currentLine:
|
||||||
dw 0x0000
|
db 0
|
||||||
LBA_selectionB:
|
timeoutTicks:
|
||||||
dw 0x0000
|
dw 0, 0
|
||||||
selection:
|
|
||||||
dw 0x0000
|
bootSectorDAP:
|
||||||
position:
|
istruc AddressPacket
|
||||||
dw 0x091D
|
at AddressPacket.packet_size, db 0x10
|
||||||
lenght:
|
at AddressPacket.block_count, db 0x01
|
||||||
dw 0x0000
|
at AddressPacket.buffer, dw 0x0000, 0x07c0
|
||||||
colour:
|
iend
|
||||||
dw 0x0000
|
|
||||||
first_position:
|
kColorTable:
|
||||||
dw 0x091F
|
db BLUE, RED, CYAN, GREEN
|
||||||
nobots:
|
kReadError:
|
||||||
db 'Boot sector signature not found', 0x00
|
db 'Error loading sectors', 0x00
|
||||||
error:
|
kNoBootablePartitionError:
|
||||||
db 'Error loading sectors', 0x00
|
db 'Not a bootable partition', 0x00
|
||||||
yeah:
|
kBootMessage:
|
||||||
db 'Boot!', 0x00
|
db 'Boot!', 0x00
|
||||||
|
|
||||||
|
|
||||||
|
listItemCount:
|
||||||
|
defaultItem equ listItemCount + 2
|
||||||
|
timeout equ defaultItem + 2
|
||||||
|
list equ timeout + 2
|
||||||
|
|
||||||
|
; dw number of entries
|
||||||
|
; dw the default entry
|
||||||
|
; dw the timeout (-1 for none)
|
||||||
|
; entry:
|
||||||
|
; db size of partition name 0-terminated string
|
||||||
|
; db 0-terminated string with partition name
|
||||||
|
; quadword start sector
|
||||||
|
|
||||||
list_items:
|
%if USE_TEST_MENU
|
||||||
dw 0x06
|
dw 0x06
|
||||||
list:
|
|
||||||
db 0x05
|
dw 2
|
||||||
db 'HAIKU' , 0x80
|
|
||||||
dw 0x003E
|
dw 5
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
db 0x07
|
db 0x06
|
||||||
db 'FreeBSD' , 0x80
|
db 'HAIKU', 0
|
||||||
dw 0x003F
|
dw 1, 0, 0, 0
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
db 0x03
|
db 0x08
|
||||||
db 'DOS' , 0x80
|
db 'FreeBSD', 0
|
||||||
dw 0x003E
|
dw 0x003F, 0, 0, 0
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
db 0x05
|
db 0x04
|
||||||
db 'LINUX' , 0x80
|
db 'DOS', 0
|
||||||
dw 0x003F
|
dw 0x003E, 0, 0, 0
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
db 0x07
|
|
||||||
db 'BeOS R5' , 0x80
|
|
||||||
dw 0x003F
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
db 0x07
|
|
||||||
db 'OpenBSD' , 0x80
|
|
||||||
dw 0xAAAA
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
ChainLoad_DAP:
|
|
||||||
db 0x10 ; Size of DAP
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
db 0x01 ; number of sectors to read
|
|
||||||
db 0x00 ; unused (zero)
|
|
||||||
dw 0x0000 ; segment:offset pointer to buffer
|
|
||||||
dw 0x07C0 ; segment:offset pointer to buffer
|
|
||||||
dw 0x003F ; LBA address
|
|
||||||
dw 0x0000
|
|
||||||
dw 0x0000
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
|
db 0x06
|
||||||
|
db 'LINUX', 0
|
||||||
|
dw 0x003F, 0, 0, 0
|
||||||
|
|
||||||
|
db 0x08
|
||||||
|
db 'BeOS R5', 0
|
||||||
|
dw 0x003F, 0, 0, 0
|
||||||
|
|
||||||
|
db 0x07
|
||||||
|
db 'OpenBSD', 0
|
||||||
|
dw 0xAAAA, 0, 0, 0
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user