1b76ca311SAxel Dörfler; 2b76ca311SAxel Dörfler; Copyright 2007, Dengg David, david-d@gmx.at. All rights reserved. 3b76ca311SAxel Dörfler; Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved. 4b76ca311SAxel Dörfler; Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. 549c044abSAxel Dörfler; Copyright 2011, Axel Dörfler, axeld@pinc-software.de. 6b76ca311SAxel Dörfler; Distributed under the terms of the MIT License. 7b76ca311SAxel Dörfler 8b76ca311SAxel Dörfler 9b76ca311SAxel Dörfler%assign USE_TEST_MENU 0 10b76ca311SAxel Dörfler 11b76ca311SAxel Dörfler%assign BOOT_BLOCK_START_ADDRESS 0x7c00 12b76ca311SAxel Dörfler 13b76ca311SAxel Dörfler%assign MBR_SIGNATURE 0xAA55 14b76ca311SAxel Dörfler 15b76ca311SAxel Dörfler; BIOS calls 16b76ca311SAxel Dörfler 17b76ca311SAxel Dörfler%assign BIOS_VIDEO_SERVICES 0x10 18b76ca311SAxel Dörfler%assign BIOS_DISK_SERVICES 0x13 19b76ca311SAxel Dörfler%assign BIOS_KEYBOARD_SERVICES 0x16 20b76ca311SAxel Dörfler%assign BIOS_REBOOT 0x19 ; dl - boot drive number 21b76ca311SAxel Dörfler%assign BIOS_TIME_SERVICES 0x1A 22b76ca311SAxel Dörfler 23b76ca311SAxel Dörfler; video services 24b76ca311SAxel Dörfler%assign SET_VIDEO_MODE 0x00 ; al - mode 25b76ca311SAxel Dörfler 26b76ca311SAxel Dörfler%assign SET_CURSOR_SHAPE 0x01 ; ch - starting scan line (5 bits) 27b76ca311SAxel Dörfler ; cl - ending scan line (5 bits) 28b76ca311SAxel Dörfler 29b76ca311SAxel Dörfler%assign SET_CURSOR 0x02 ; dl - column 30b76ca311SAxel Dörfler ; dh - row 31b76ca311SAxel Dörfler ; bh - page 32b76ca311SAxel Dörfler 33b76ca311SAxel Dörfler 34b76ca311SAxel Dörfler%assign GET_CURSOR 0x03 ; bh - page 35b76ca311SAxel Dörfler ; -> dl - column 36b76ca311SAxel Dörfler ; dh - row 37b76ca311SAxel Dörfler ; Cursor shape: 38b76ca311SAxel Dörfler ; ch - starting scan line 39b76ca311SAxel Dörfler ; cl - ending scan line 40b76ca311SAxel Dörfler 41b76ca311SAxel Dörfler%assign SCROLL_UP 0x06 ; al - lines (0: clear screen) 42b76ca311SAxel Dörfler ; bh - attribute 43b76ca311SAxel Dörfler ; ch - upper line 44b76ca311SAxel Dörfler ; cl - left column 45b76ca311SAxel Dörfler ; dh - lower line 46b76ca311SAxel Dörfler ; dl - right column 47b76ca311SAxel Dörfler 48b76ca311SAxel Dörfler%assign WRITE_CHAR 0x09 ; al - char 49b76ca311SAxel Dörfler ; bh - page 50b76ca311SAxel Dörfler ; bl - attribute 51b76ca311SAxel Dörfler ; cx - count 52b76ca311SAxel Dörfler 53b76ca311SAxel Dörfler;%assign WRITE_CHAR 0x0e ; al - char 54b76ca311SAxel Dörfler ; bh - page 55b76ca311SAxel Dörfler ; bl - foreground color (graphics mode only) 56b76ca311SAxel Dörfler 57b76ca311SAxel Dörfler; disk services 58b76ca311SAxel Dörfler%assign READ_DISK_SECTORS 0x02 ; dl - drive 59b76ca311SAxel Dörfler ; es:bx - buffer 60b76ca311SAxel Dörfler ; dh - head (0 - 15) 61b76ca311SAxel Dörfler ; ch - track 7:0 (0 - 1023) 62b76ca311SAxel Dörfler ; cl - track 9:8, 63b76ca311SAxel Dörfler ; sector (1 - 17) 64b76ca311SAxel Dörfler ; al - sector count 65b76ca311SAxel Dörfler ; -> al - sectors read 66b76ca311SAxel Dörfler%assign READ_DRIVE_PARAMETERS 0x08 ; dl - drive 67b76ca311SAxel Dörfler ; -> cl - max cylinder 9:8 68b76ca311SAxel Dörfler ; - sectors per track 69b76ca311SAxel Dörfler ; ch - max cylinder 7:0 70b76ca311SAxel Dörfler ; dh - max head 71b76ca311SAxel Dörfler ; dl - number of drives (?) 72b76ca311SAxel Dörfler%assign CHECK_DISK_EXTENSIONS_PRESENT 0x41 ; bx - 0x55aa 73b76ca311SAxel Dörfler ; dl - drive 74b76ca311SAxel Dörfler ; -> success: carry clear 75b76ca311SAxel Dörfler ; ah - extension version 76b76ca311SAxel Dörfler ; bx - 0xaa55 77b76ca311SAxel Dörfler ; cx - support bit mask 78b76ca311SAxel Dörfler ; -> error: carry set 79b76ca311SAxel Dörfler%assign EXTENDED_READ 0x42 ; dl - drive 80b76ca311SAxel Dörfler ; ds:si - address packet 81b76ca311SAxel Dörfler ; -> success: carry clear 82b76ca311SAxel Dörfler ; -> error: carry set 83b76ca311SAxel Dörfler 84b76ca311SAxel Dörfler%assign FIXED_DISK_SUPPORT 0x1 ; flag indicating fixed disk 85b76ca311SAxel Dörfler ; extension command subset 86b76ca311SAxel Dörfler 87b76ca311SAxel Dörfler; keyboard services 88b76ca311SAxel Dörfler%assign READ_CHAR 0x00 ; -> al - ASCII char 89b76ca311SAxel Dörfler ; ah - scan code 90b76ca311SAxel Dörfler 91b76ca311SAxel Dörfler%assign PROBE_CHAR 0x01 ; -> zf = 0 92b76ca311SAxel Dörfler ; al - ASCII char 93b76ca311SAxel Dörfler ; ah - scan code 94b76ca311SAxel Dörfler 95b76ca311SAxel Dörfler%assign GET_MODIFIER_KEYS 0x02 ;-> al - modifier key bitmask 96b76ca311SAxel Dörfler 97b76ca311SAxel Dörfler; timer services 98b76ca311SAxel Dörfler%assign READ_CLOCK 0x00 ; -> cx - high word 99b76ca311SAxel Dörfler ; dx - low word 100b76ca311SAxel Dörfler ; one tick = 1/18.2s 101b76ca311SAxel Dörfler 102b76ca311SAxel Dörfler%assign TICKS_PER_SECOND 19 103b76ca311SAxel Dörfler 104b76ca311SAxel Dörfler; video modes 105b76ca311SAxel Dörfler%assign GRAPHIC_MODE_80x25 0x12 ; 640 x 480 graphic mode 106b76ca311SAxel Dörfler 107b76ca311SAxel Dörfler%assign TEXT_COLUMNS 80 ; Number of columns 108b76ca311SAxel Dörfler%assign TEXT_ROWS 25 ; Number of rows 109b76ca311SAxel Dörfler 110b76ca311SAxel Dörfler; Colors 111b76ca311SAxel Dörfler%assign BLACK 0 112b76ca311SAxel Dörfler%assign BLUE 1 113b76ca311SAxel Dörfler%assign GREEN 2 114b76ca311SAxel Dörfler%assign CYAN 3 115b76ca311SAxel Dörfler%assign RED 4 116b76ca311SAxel Dörfler%assign MAGENTA 5 117b76ca311SAxel Dörfler%assign BROWN 6 118b76ca311SAxel Dörfler%assign LIGHT_GRAY 7 119b76ca311SAxel Dörfler%assign DARK_GRAY 8 120b76ca311SAxel Dörfler%assign LIGHT_BLUE 9 121b76ca311SAxel Dörfler%assign LIGHT_GREEN 10 122b76ca311SAxel Dörfler%assign LIGHT_CYAN 11 123b76ca311SAxel Dörfler%assign LIGHT_RED 12 124b76ca311SAxel Dörfler%assign LIGHT_MAGENTA 13 125b76ca311SAxel Dörfler%assign YELLOW 14 126b76ca311SAxel Dörfler%assign WHITE 15 127b76ca311SAxel Dörfler 128b76ca311SAxel Dörfler%assign BRIGHT_COLOR_MASK 8 129b76ca311SAxel Dörfler 130b76ca311SAxel Dörfler; Characters 131b76ca311SAxel Dörfler%assign TRIANGLE_TO_RIGHT 16 132b76ca311SAxel Dörfler%assign TRIANGLE_TO_LEFT 17 133b76ca311SAxel Dörfler 134b76ca311SAxel Dörfler; Key codes 135b76ca311SAxel Dörfler%assign KEY_DOWN 0x50 136b76ca311SAxel Dörfler%assign KEY_UP 0x48 137b76ca311SAxel Dörfler%assign KEY_RETURN 0x1C 138b76ca311SAxel Dörfler 139b76ca311SAxel Dörfler; Modifier key bitmasks 140b76ca311SAxel Dörfler%assign MODIFIER_RIGHT_SHIFT_KEY 0x01 141b76ca311SAxel Dörfler%assign MODIFIER_LEFT_SHIFT_KEY 0x02 142b76ca311SAxel Dörfler%assign MODIFIER_CONTROL_KEY 0x04 143b76ca311SAxel Dörfler%assign MODIFIER_ALT_KEY 0x08 144b76ca311SAxel Dörfler%assign MODIFIER_SCROLL_LOCK_KEY 0x10 145b76ca311SAxel Dörfler%assign MODIFIER_NUM_LOCK_KEY 0x20 146b76ca311SAxel Dörfler%assign MODIFIER_CAPS_LOCK_KEY 0x40 147b76ca311SAxel Dörfler%assign MODIFIER_INSERT_KEY 0x80 148b76ca311SAxel Dörfler 149b76ca311SAxel Dörfler; String constants with their length 150b76ca311SAxel Dörfler%define TITLE 'Haiku Boot Manager' 151b76ca311SAxel Dörfler%strlen TITLE_LENGTH TITLE 152b76ca311SAxel Dörfler%define SELECT_OS_MESSAGE 'Select an OS from the menu' 153b76ca311SAxel Dörfler%strlen SELECT_OS_MESSAGE_LENGTH SELECT_OS_MESSAGE 154b76ca311SAxel Dörfler 155b76ca311SAxel Dörfler; 16 bit code 156*74a14969SFrançois RevolSECTION .text 157b76ca311SAxel DörflerBITS 16 158b76ca311SAxel Dörfler 159b76ca311SAxel Dörfler 160b76ca311SAxel Dörfler; nicer way to get the size of a structure 161b76ca311SAxel Dörfler%define sizeof(s) s %+ _size 162b76ca311SAxel Dörfler 163b76ca311SAxel Dörfler; using a structure in a another structure definition 164b76ca311SAxel Dörfler%macro nstruc 1-2 1 165b76ca311SAxel Dörfler resb sizeof(%1) * %2 166b76ca311SAxel Dörfler%endmacro 167b76ca311SAxel Dörfler 168b76ca311SAxel Dörfler; Variables on stack 169b76ca311SAxel Dörflerstruc Locals 170b76ca311SAxel Dörfler selection resw 1 171b76ca311SAxel Dörfler firstLine resb 2 ; low byte used only 172b76ca311SAxel Dörfler timeoutTicks resd 1 173b76ca311SAxel Dörfler cursorX resb 1 174b76ca311SAxel Dörfler cursorY resb 1 175b76ca311SAxel Dörfler cursorShape resw 1 17689f0e174SAxel Dörfler biosDrive resb 1 177b76ca311SAxel Dörflerendstruc 178b76ca311SAxel Dörfler 179b76ca311SAxel DörflercursorPosition equ cursorX 180b76ca311SAxel Dörfler 181b76ca311SAxel Dörfler%macro DEBUG_PAUSE 0 182b76ca311SAxel Dörfler push ax 183b76ca311SAxel Dörfler mov ah, READ_CHAR 184b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES 185b76ca311SAxel Dörfler pop ax 186b76ca311SAxel Dörfler%endmacro 187b76ca311SAxel Dörfler 188b76ca311SAxel Dörfler%macro CLEAR_SCREEN 0 189b76ca311SAxel Dörfler mov ah, SCROLL_UP 190b76ca311SAxel Dörfler xor al, al 191b76ca311SAxel Dörfler mov bh, WHITE 192b76ca311SAxel Dörfler xor cx, cx 193b76ca311SAxel Dörfler mov dx, (TEXT_ROWS-1) * 0x100 + (TEXT_COLUMNS-1) 194b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 195b76ca311SAxel Dörfler%endmacro 196b76ca311SAxel Dörfler 197b76ca311SAxel Dörfler; Prints a null terminated string 198b76ca311SAxel Dörfler; bl ... color 199b76ca311SAxel Dörfler; si ... offset to string 200b76ca311SAxel Dörfler%macro PRINT_STRING 0 201b76ca311SAxel Dörfler push ax 202b76ca311SAxel Dörfler push bx 203b76ca311SAxel Dörfler push cx 204b76ca311SAxel Dörfler push dx 205b76ca311SAxel Dörfler xor bh, bh ; write on page 0 206b76ca311SAxel Dörfler jmp .loop_condition 207b76ca311SAxel Dörfler.loop 208b76ca311SAxel Dörfler mov dx, [bp + cursorPosition] 209b76ca311SAxel Dörfler mov ah, SET_CURSOR 210b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 211b76ca311SAxel Dörfler 212b76ca311SAxel Dörfler inc byte [bp + cursorX] 213b76ca311SAxel Dörfler 214b76ca311SAxel Dörfler mov cx, 1 215b76ca311SAxel Dörfler mov ah, WRITE_CHAR 216b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 217b76ca311SAxel Dörfler.loop_condition 218b76ca311SAxel Dörfler lodsb 219b76ca311SAxel Dörfler cmp al, 0 220b76ca311SAxel Dörfler jnz .loop 221b76ca311SAxel Dörfler pop dx 222b76ca311SAxel Dörfler pop cx 223b76ca311SAxel Dörfler pop bx 224b76ca311SAxel Dörfler pop ax 225b76ca311SAxel Dörfler ret 226b76ca311SAxel Dörfler%endmacro 227b76ca311SAxel Dörfler 228b76ca311SAxel Dörfler; 64 bit value 229b76ca311SAxel Dörflerstruc quadword 230b76ca311SAxel Dörfler .lower resd 1 231b76ca311SAxel Dörfler .upper resd 1 232b76ca311SAxel Dörflerendstruc 233b76ca311SAxel Dörfler 234b76ca311SAxel Dörfler; address packet as required by the EXTENDED_READ BIOS call 235b76ca311SAxel Dörflerstruc AddressPacket 236b76ca311SAxel Dörfler .packet_size resb 1 237b76ca311SAxel Dörfler .reserved1 resb 1 238b76ca311SAxel Dörfler .block_count resb 1 239b76ca311SAxel Dörfler .reserved2 resb 1 240b76ca311SAxel Dörfler .buffer resd 1 241b76ca311SAxel Dörfler .offset nstruc quadword 242b76ca311SAxel Dörflerendstruc 243b76ca311SAxel Dörfler 244b76ca311SAxel Dörflerstruc BootLoaderAddress 245b76ca311SAxel Dörfler .device resb 1 ; hard drive number 246b76ca311SAxel Dörfler .offset nstruc quadword ; LBA of start start sector 247b76ca311SAxel Dörflerendstruc 248b76ca311SAxel Dörfler 249b76ca311SAxel Dörfler; use code available in stage 1 250b76ca311SAxel Dörfler%define printstr printStringStage1 251b76ca311SAxel Dörfler 252b76ca311SAxel Dörflerstage1: 25349c044abSAxel Dörfler mov ax, 0x07c0 ; BOOT_BLOCK_START_ADDRESS / 16 254b76ca311SAxel Dörfler mov ds, ax ; Setup segment registers 255b76ca311SAxel Dörfler mov es, ax 256b76ca311SAxel Dörfler mov ss, ax 257b76ca311SAxel Dörfler 258b76ca311SAxel Dörfler mov sp, 0xFFFF - sizeof(Locals) ; Make stack empty 259b76ca311SAxel Dörfler mov bp, sp 260b76ca311SAxel Dörfler 26189f0e174SAxel Dörfler mov [bp + biosDrive], dl ; Store boot drive 26249c044abSAxel Dörfler cld ; String operations increment index 26349c044abSAxel Dörfler ; registers 264b76ca311SAxel Dörfler CLEAR_SCREEN 265b76ca311SAxel Dörfler call hideCursor 266b76ca311SAxel Dörfler 267b76ca311SAxel Dörfler mov bh, 0 ; Text output on page 0 268b76ca311SAxel Dörfler 269b76ca311SAxel Dörfler ; Print title centered at row 2 270b76ca311SAxel Dörfler mov dx, 1 * 0x100 + (40 - TITLE_LENGTH / 2) 271b76ca311SAxel Dörfler mov [bp + cursorPosition], dx 272b76ca311SAxel Dörfler 273b76ca311SAxel Dörfler mov si, kTitle 274b76ca311SAxel Dörfler mov bl, WHITE 275b76ca311SAxel Dörfler call printstr 276b76ca311SAxel Dörfler 277b76ca311SAxel Dörfler ; Print message centered at second last row 278b76ca311SAxel Dörfler mov dx, (TEXT_ROWS-2) * 0x100 + (40 - SELECT_OS_MESSAGE_LENGTH / 2) 279b76ca311SAxel Dörfler mov [bp + cursorPosition], dx 280b76ca311SAxel Dörfler 281b76ca311SAxel Dörfler mov bl, LIGHT_GRAY 282b76ca311SAxel Dörfler mov si, kSelectOSMessage 283b76ca311SAxel Dörfler call printstr 284b76ca311SAxel Dörfler 285b76ca311SAxel Dörfler ; Chain load rest of boot loader 286b76ca311SAxel Dörfler mov ah, EXTENDED_READ ; Load 3 more sectors 28789f0e174SAxel Dörfler mov dl, [bp + biosDrive] 288b76ca311SAxel Dörfler mov si, nextStageDAP 289b76ca311SAxel Dörfler int BIOS_DISK_SERVICES 290b76ca311SAxel Dörfler jc .error ; I/O error 291b76ca311SAxel Dörfler jmp stage2 ; Continue in loaded stage 2 292b76ca311SAxel Dörfler 293b76ca311SAxel Dörfler.error: 294b76ca311SAxel Dörfler call showCursor 295b76ca311SAxel Dörfler mov si, kError 296b76ca311SAxel Dörfler mov bl, RED 297b76ca311SAxel Dörfler call printstr 298b76ca311SAxel Dörfler 299b76ca311SAxel Dörfler mov ah, READ_CHAR 300b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES 301b76ca311SAxel Dörfler 30289f0e174SAxel Dörfler mov dl, [bp + biosDrive] 303b76ca311SAxel Dörfler int BIOS_REBOOT 304b76ca311SAxel Dörfler 305b76ca311SAxel DörflerprintStringStage1: 306b76ca311SAxel Dörfler PRINT_STRING 307b76ca311SAxel Dörfler 308b76ca311SAxel DörflerhideCursor: 309b76ca311SAxel Dörfler mov ah, GET_CURSOR 310b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 311b76ca311SAxel Dörfler mov [bp + cursorShape], cx 312b76ca311SAxel Dörfler 313b76ca311SAxel Dörfler mov ah, SET_CURSOR_SHAPE 314b76ca311SAxel Dörfler mov cx, 0x2000 315b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 316b76ca311SAxel Dörfler ret 317b76ca311SAxel Dörfler 318b76ca311SAxel DörflershowCursor: 319b76ca311SAxel Dörfler mov cx, [bp + cursorShape] 320b76ca311SAxel Dörfler mov ah, SET_CURSOR_SHAPE 321b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 322b76ca311SAxel Dörfler ret 323b76ca311SAxel Dörfler 324b76ca311SAxel DörflernextStageDAP: 325b76ca311SAxel Dörfler istruc AddressPacket 326b76ca311SAxel Dörfler at AddressPacket.packet_size, db 0x10 327b76ca311SAxel Dörfler at AddressPacket.block_count, db 0x03 328b76ca311SAxel Dörfler at AddressPacket.buffer, dw 0x0200, 0x07c0 329b76ca311SAxel Dörfler at AddressPacket.offset, dw 1 330b76ca311SAxel Dörfler iend 331b76ca311SAxel Dörfler 332b76ca311SAxel DörflerkTitle: 333b76ca311SAxel Dörfler db TITLE, 0x00 334b76ca311SAxel DörflerkSelectOSMessage: 335b76ca311SAxel Dörfler db SELECT_OS_MESSAGE, 0x00 336b76ca311SAxel DörflerkError: 337b76ca311SAxel Dörfler db 'Error loading sectors!', 0x00 338b76ca311SAxel Dörfler 339b76ca311SAxel DörflerkStage1UnusedSpace equ 440 - ($-$$) 340b76ca311SAxel Dörfler ; Fill the missing space to reach byte 440 341b76ca311SAxel Dörfler times kStage1UnusedSpace db 'B' 342b76ca311SAxel Dörfler 343cf3c703bSFrançois RevolkDiskSignature: 344b76ca311SAxel Dörfler dw 0, 0 345b76ca311SAxel DörflerkReserved 346b76ca311SAxel Dörfler dw 0 347b76ca311SAxel DörflerkPartitionTable 348b76ca311SAxel Dörfler times 64 db 0 349b76ca311SAxel Dörfler 350b76ca311SAxel DörflerkMBRSignature: 351b76ca311SAxel Dörfler ; Magic marker "AA55" (to identify a valid boot record) 352b76ca311SAxel Dörfler dw MBR_SIGNATURE 353b76ca311SAxel Dörfler 354b76ca311SAxel Dörfler; ====================================================================== 355b76ca311SAxel Dörfler; ======================= SECOND SECTOR ================================ 356b76ca311SAxel Dörfler; ====================================================================== 357b76ca311SAxel Dörfler 35889f0e174SAxel Dörfler; Use code available in stage 2 359b76ca311SAxel Dörfler%define printstr printStringStage2 360b76ca311SAxel Dörfler 361b76ca311SAxel Dörfler%assign TIMEOUT_OFF 0xffff 362b76ca311SAxel Dörfler 363b76ca311SAxel Dörfler 364b76ca311SAxel Dörflerstage2: 365b76ca311SAxel Dörfler mov ax, [defaultItem] ; Select default item 366b76ca311SAxel Dörfler mov [bp + selection], ax 367b76ca311SAxel Dörfler 368b76ca311SAxel Dörfler mov ax, TICKS_PER_SECOND ; Calculate timeout ticks 369b76ca311SAxel Dörfler mul word [timeout] 370b76ca311SAxel Dörfler mov bx, dx 371b76ca311SAxel Dörfler push ax 372b76ca311SAxel Dörfler 373b76ca311SAxel Dörfler mov ah, READ_CLOCK 374b76ca311SAxel Dörfler int BIOS_TIME_SERVICES 375b76ca311SAxel Dörfler 376b76ca311SAxel Dörfler pop ax ; Add current ticks 377b76ca311SAxel Dörfler add ax, dx 378b76ca311SAxel Dörfler adc bx, cx 379b76ca311SAxel Dörfler mov [bp + timeoutTicks], ax 380b76ca311SAxel Dörfler mov [bp + timeoutTicks + 2], bx 381b76ca311SAxel Dörfler 382b76ca311SAxel Dörfler mov al, [listItemCount] ; Calculate start row for menu 383b76ca311SAxel Dörfler shr al, 1 384b76ca311SAxel Dörfler mov bl, TEXT_ROWS / 2 385b76ca311SAxel Dörfler sub bl, al ; y = TEXT_ROWS / 2 - number of items / 2 386b76ca311SAxel Dörfler mov [bp + firstLine], bl 387b76ca311SAxel Dörfler 388b76ca311SAxel Dörfler mov ah, GET_MODIFIER_KEYS ; Disable timeout if ALT key is pressed 389b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES 390b76ca311SAxel Dörfler and al, MODIFIER_ALT_KEY 391b76ca311SAxel Dörfler jz showMenu 392b76ca311SAxel Dörfler mov word [timeout], TIMEOUT_OFF 393b76ca311SAxel Dörfler 394b76ca311SAxel DörflershowMenu: 395b76ca311SAxel Dörfler call printMenu 396b76ca311SAxel Dörfler 397b76ca311SAxel Dörfler cmp word [timeout], TIMEOUT_OFF 398b76ca311SAxel Dörfler je inputLoop 399b76ca311SAxel Dörfler 400b76ca311SAxel DörflertimeoutLoop: 401b76ca311SAxel Dörfler mov ah, PROBE_CHAR 402b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES 403b76ca311SAxel Dörfler jnz inputLoop ; cancel timeout if key is pressed 404b76ca311SAxel Dörfler call isTimeoutReached 405b76ca311SAxel Dörfler jnc timeoutLoop 406b76ca311SAxel Dörfler jmp bootSelectedPartition 407b76ca311SAxel Dörfler 408b76ca311SAxel DörflerisTimeoutReached: 409b76ca311SAxel Dörfler mov ah, READ_CLOCK 410b76ca311SAxel Dörfler int BIOS_TIME_SERVICES 411b76ca311SAxel Dörfler cmp cx, [bp + timeoutTicks + 2] 412b76ca311SAxel Dörfler jb .returnFalse 413b76ca311SAxel Dörfler ja .returnTrue 414b76ca311SAxel Dörfler cmp dx, [bp + timeoutTicks] 415b76ca311SAxel Dörfler ja .returnTrue 416b76ca311SAxel Dörfler.returnFalse: 417b76ca311SAxel Dörfler clc 418b76ca311SAxel Dörfler ret 419b76ca311SAxel Dörfler.returnTrue: 420b76ca311SAxel Dörfler stc 421b76ca311SAxel Dörfler ret 422b76ca311SAxel Dörfler 423b76ca311SAxel Dörfler; ================== Wait for a key and do something with it ================== 424b76ca311SAxel DörflermainLoop: 425b76ca311SAxel Dörfler call printMenu 426b76ca311SAxel Dörfler 427b76ca311SAxel DörflerinputLoop: 428b76ca311SAxel Dörfler mov ah, READ_CHAR 429b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES ; AL = ASCII Code, AH = Scancode 430b76ca311SAxel Dörfler 431b76ca311SAxel Dörfler cmp ah, KEY_DOWN 432b76ca311SAxel Dörfler je selectNextPartition 433b76ca311SAxel Dörfler 434b76ca311SAxel Dörfler cmp ah, KEY_UP 435b76ca311SAxel Dörfler je selectPreviousPartition 436b76ca311SAxel Dörfler 437b76ca311SAxel Dörfler cmp ah, KEY_RETURN 438b76ca311SAxel Dörfler jne inputLoop 439b76ca311SAxel Dörfler jmp bootSelectedPartition 440b76ca311SAxel Dörfler 441b76ca311SAxel DörflerselectNextPartition: 442b76ca311SAxel Dörfler mov ax, [bp + selection] 443b76ca311SAxel Dörfler inc ax 444b76ca311SAxel Dörfler cmp ax, [listItemCount] 445b76ca311SAxel Dörfler jne .done ; At end of list? 446b76ca311SAxel Dörfler xor ax, ax ; Then jump to first entry 447b76ca311SAxel Dörfler.done: 448b76ca311SAxel Dörfler mov [bp + selection], ax 449b76ca311SAxel Dörfler jmp mainLoop 450b76ca311SAxel Dörfler 451b76ca311SAxel DörflerselectPreviousPartition: 452b76ca311SAxel Dörfler mov ax, [bp + selection] 453b76ca311SAxel Dörfler or ax, ax 454b76ca311SAxel Dörfler jnz .done ; At top of list? 455b76ca311SAxel Dörfler mov ax, [listItemCount] ; Then jump to last entry 456b76ca311SAxel Dörfler.done: 457b76ca311SAxel Dörfler dec ax 458b76ca311SAxel Dörfler mov [bp + selection], ax 459b76ca311SAxel Dörfler jmp mainLoop 460b76ca311SAxel Dörfler 461b76ca311SAxel Dörfler 462b76ca311SAxel Dörfler; ======================= Print the OS list ============================ 463b76ca311SAxel DörflerprintMenu: 464b76ca311SAxel Dörfler mov al, [bp + firstLine] 465b76ca311SAxel Dörfler mov [bp + cursorY], al 466b76ca311SAxel Dörfler 467b76ca311SAxel Dörfler mov si, list ; Start at top of list 468b76ca311SAxel Dörfler xor cx, cx ; The index of the current item 469b76ca311SAxel Dörfler 470b76ca311SAxel Dörfler.loop: 471b76ca311SAxel Dörfler lodsb ; String length incl. 0-terminator 472b76ca311SAxel Dörfler add al, 3 ; center menu item 473b76ca311SAxel Dörfler shr al, 1 ; x = TEXT_COLUMNS / 2 - length / 2 474b76ca311SAxel Dörfler mov dl, TEXT_COLUMNS / 2 475b76ca311SAxel Dörfler sub dl, al 476b76ca311SAxel Dörfler mov [bp + cursorX], dl 477b76ca311SAxel Dörfler 478b76ca311SAxel Dörfler mov al, TRIANGLE_TO_RIGHT 479b76ca311SAxel Dörfler call updateMarker 480b76ca311SAxel Dörfler inc byte [bp + cursorX] 481b76ca311SAxel Dörfler 482b76ca311SAxel Dörfler mov di, cx 483b76ca311SAxel Dörfler and di, 3 484b76ca311SAxel Dörfler mov bl, [kColorTable + di] ; Text color 485b76ca311SAxel Dörfler 486b76ca311SAxel Dörfler cmp cx, [bp + selection] 487b76ca311SAxel Dörfler jne .print ; Selected item reached? 488b76ca311SAxel Dörfler xor bl, BRIGHT_COLOR_MASK ; Highlight it 489b76ca311SAxel Dörfler 490b76ca311SAxel Dörfler.print: 491b76ca311SAxel Dörfler call printstr 492b76ca311SAxel Dörfler add si, sizeof(BootLoaderAddress) 493b76ca311SAxel Dörfler 494b76ca311SAxel Dörfler add byte [bp + cursorX], 1 495b76ca311SAxel Dörfler mov al, TRIANGLE_TO_LEFT 496b76ca311SAxel Dörfler call updateMarker 497b76ca311SAxel Dörfler 498b76ca311SAxel Dörfler inc byte [bp + cursorY] 499b76ca311SAxel Dörfler inc cx 500b76ca311SAxel Dörfler 501b76ca311SAxel Dörfler cmp cx, [listItemCount] 502b76ca311SAxel Dörfler jne .loop 503b76ca311SAxel Dörfler ret 504b76ca311SAxel Dörfler 505b76ca311SAxel DörflerupdateMarker: 506b76ca311SAxel Dörfler cmp cx, [bp + selection] 507b76ca311SAxel Dörfler je .print 508b76ca311SAxel Dörfler mov al, ' ' ; Clear marker 509b76ca311SAxel Dörfler.print 510b76ca311SAxel Dörfler mov bl, WHITE 511b76ca311SAxel Dörfler jmp printChar ; return from subroutine 512b76ca311SAxel Dörfler 513b76ca311SAxel Dörfler 514b76ca311SAxel Dörfler; ========================== Chainload ========================== 515b76ca311SAxel Dörfler 516b76ca311SAxel DörflerbootSelectedPartition: 517b76ca311SAxel Dörfler 518b76ca311SAxel Dörfler call showCursor 519b76ca311SAxel Dörfler 520b76ca311SAxel Dörfler call getSelectedBootLoaderAddress 521b76ca311SAxel Dörfler lodsb ; Set boot drive 522b76ca311SAxel Dörfler mov dl, al 523b76ca311SAxel Dörfler 524b76ca311SAxel Dörfler mov di, bootSectorDAP+AddressPacket.offset ; Copy start sector 525b76ca311SAxel Dörfler mov cx, 4 ; It is stored in a quad word 526b76ca311SAxel Dörfler.copy_start_sector 527b76ca311SAxel Dörfler lodsw 528b76ca311SAxel Dörfler stosw 529b76ca311SAxel Dörfler loop .copy_start_sector 530b76ca311SAxel Dörfler 531b76ca311SAxel Dörfler mov ah, EXTENDED_READ ; Now read start sector from HD 532b76ca311SAxel Dörfler mov si, bootSectorDAP 533b76ca311SAxel Dörfler int BIOS_DISK_SERVICES 534b76ca311SAxel Dörfler mov si, kReadError 535b76ca311SAxel Dörfler jc printAndHalt ; Failed to read sector 536b76ca311SAxel Dörfler 537b76ca311SAxel Dörfler mov ax, [kMBRSignature] 538b76ca311SAxel Dörfler cmp ax, MBR_SIGNATURE 539b76ca311SAxel Dörfler mov si, kNoBootablePartitionError 540b76ca311SAxel Dörfler jne printAndHalt ; Missing signature 541b76ca311SAxel Dörfler 542b76ca311SAxel Dörfler CLEAR_SCREEN 543b76ca311SAxel Dörfler 544b76ca311SAxel Dörfler ; Print "Loading <name>" at top of screen 545b76ca311SAxel Dörfler mov word [bp + cursorPosition], 0 546b76ca311SAxel Dörfler mov si, kLoadingMessage 547b76ca311SAxel Dörfler mov bl, LIGHT_GRAY 548b76ca311SAxel Dörfler call printstr 549b76ca311SAxel Dörfler 550b76ca311SAxel Dörfler inc byte [bp + cursorX] 551b76ca311SAxel Dörfler call getSelectedMenuItem 552b76ca311SAxel Dörfler inc si ; Skip string length byte 553b76ca311SAxel Dörfler call printstr 554b76ca311SAxel Dörfler 555b76ca311SAxel Dörfler mov dx, 0x100 556b76ca311SAxel Dörfler xor bh, bh 557b76ca311SAxel Dörfler mov ah, SET_CURSOR 558b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 559b76ca311SAxel Dörfler 560b76ca311SAxel Dörfler call getSelectedBootLoaderAddress 561b76ca311SAxel Dörfler mov dl, [si] ; drive number in dl 562b76ca311SAxel Dörfler 563b76ca311SAxel Dörfler jmp $$ ; Start loaded boot loader 564b76ca311SAxel Dörfler 565b76ca311SAxel Dörfler 566b76ca311SAxel DörflerprintAndHalt: 567b76ca311SAxel Dörfler mov dx, (TEXT_ROWS-4) * 0x100 + (TEXT_COLUMNS / 3) 568b76ca311SAxel Dörfler mov [bp + cursorPosition], dx 569b76ca311SAxel Dörfler 570b76ca311SAxel Dörfler mov bx, 0x0F ; Page number and foreground color 571b76ca311SAxel Dörfler call printstr 572b76ca311SAxel Dörfler mov ah, READ_CHAR 573b76ca311SAxel Dörfler int BIOS_KEYBOARD_SERVICES 5740e193080SAxel Dörfler mov dl, [bp + biosDrive] 575b76ca311SAxel Dörfler int BIOS_REBOOT 576b76ca311SAxel Dörfler 577b76ca311SAxel Dörfler; Output: 578b76ca311SAxel Dörfler; si address of selected menu item 579b76ca311SAxel Dörfler; Trashes: 580b76ca311SAxel Dörfler; ax, cx 581b76ca311SAxel DörflergetSelectedMenuItem: 582b76ca311SAxel Dörfler mov si, list ; Search address of start sector 583b76ca311SAxel Dörfler ; of the selected item. 584b76ca311SAxel Dörfler mov cx, [bp + selection] 585b76ca311SAxel Dörfler inc cx ; Number of required iterations 586b76ca311SAxel Dörfler 587b76ca311SAxel Dörfler xor ah, ah ; The high-byte of the string length 588b76ca311SAxel Dörfler ; see loop body 589b76ca311SAxel Dörfler jmp .entry 590b76ca311SAxel Dörfler 591b76ca311SAxel Dörfler.loop: 592b76ca311SAxel Dörfler lodsb ; Length of menu item name 593b76ca311SAxel Dörfler add si, ax ; Skip name to BootLoaderAddess 594b76ca311SAxel Dörfler add si, sizeof(BootLoaderAddress) 595b76ca311SAxel Dörfler 596b76ca311SAxel Dörfler.entry: 597b76ca311SAxel Dörfler loop .loop 598b76ca311SAxel Dörfler ret 599b76ca311SAxel Dörfler 600b76ca311SAxel DörflergetSelectedBootLoaderAddress: 601b76ca311SAxel Dörfler call getSelectedMenuItem 602b76ca311SAxel Dörfler lodsb 603b76ca311SAxel Dörfler xor ah, ah 604b76ca311SAxel Dörfler add si, ax ; Skip name 60549c044abSAxel Dörfler mov dl, [si] 60649c044abSAxel Dörfler test dl, 0 ; if drive is 0, use boot drive 60749c044abSAxel Dörfler jz .takeOverBootDrive 60849c044abSAxel Dörfler ret 60949c044abSAxel Dörfler.takeOverBootDrive: 61089f0e174SAxel Dörfler mov dl, [bp + biosDrive] 61149c044abSAxel Dörfler mov [si], dl 612b76ca311SAxel Dörfler ret 613b76ca311SAxel Dörfler 614b76ca311SAxel DörflerprintStringStage2: 615b76ca311SAxel Dörfler PRINT_STRING 616b76ca311SAxel Dörfler 617b76ca311SAxel Dörfler; al ... ASCII character 618b76ca311SAxel Dörfler; bl ... color 619b76ca311SAxel DörflerprintChar: 620b76ca311SAxel Dörfler push ax 621b76ca311SAxel Dörfler push bx 622b76ca311SAxel Dörfler push cx 623b76ca311SAxel Dörfler push dx 624b76ca311SAxel Dörfler 625b76ca311SAxel Dörfler xor bh, bh ; Write on page 0 626b76ca311SAxel Dörfler 627b76ca311SAxel Dörfler mov dx, [bp + cursorPosition] 628b76ca311SAxel Dörfler mov ah, SET_CURSOR 629b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 630b76ca311SAxel Dörfler 631b76ca311SAxel Dörfler inc byte [bp + cursorX] 632b76ca311SAxel Dörfler 633b76ca311SAxel Dörfler mov cx, 1 634b76ca311SAxel Dörfler mov ah, WRITE_CHAR 635b76ca311SAxel Dörfler int BIOS_VIDEO_SERVICES 636b76ca311SAxel Dörfler 637b76ca311SAxel Dörfler pop dx 638b76ca311SAxel Dörfler pop cx 639b76ca311SAxel Dörfler pop bx 640b76ca311SAxel Dörfler pop ax 641b76ca311SAxel Dörfler ret 642b76ca311SAxel Dörfler 643b76ca311SAxel Dörfler; ================================ DATA =========================== 644b76ca311SAxel Dörfler 645b76ca311SAxel DörflerbootSectorDAP: 646b76ca311SAxel Dörfler istruc AddressPacket 647b76ca311SAxel Dörfler at AddressPacket.packet_size, db 0x10 648b76ca311SAxel Dörfler at AddressPacket.block_count, db 0x01 649b76ca311SAxel Dörfler at AddressPacket.buffer, dw 0x0000, 0x07c0 650b76ca311SAxel Dörfler iend 651b76ca311SAxel Dörfler 652b76ca311SAxel DörflerkColorTable: 653b76ca311SAxel Dörfler db BLUE, RED, GREEN, CYAN 654b76ca311SAxel DörflerkReadError: 655b76ca311SAxel Dörfler db 'Error loading sectors', 0x00 656b76ca311SAxel DörflerkNoBootablePartitionError: 657b76ca311SAxel Dörfler db 'Not a bootable partition', 0x00 658b76ca311SAxel DörflerkLoadingMessage: 659b76ca311SAxel Dörfler db 'Loading', 0x00 660b76ca311SAxel Dörfler 661b76ca311SAxel Dörfler 662b76ca311SAxel DörflerlistItemCount: 663b76ca311SAxel DörflerdefaultItem equ listItemCount + 2 664b76ca311SAxel Dörflertimeout equ defaultItem + 2 665b76ca311SAxel Dörflerlist equ timeout + 2 666b76ca311SAxel Dörfler 667b76ca311SAxel Dörfler; dw number of entries 668b76ca311SAxel Dörfler; dw the default entry 669b76ca311SAxel Dörfler; dw the timeout (-1 for none) 670b76ca311SAxel Dörfler; entry: 671b76ca311SAxel Dörfler; db size of partition name 0-terminated string 672b76ca311SAxel Dörfler; db 0-terminated string with partition name 673b76ca311SAxel Dörfler; db hard drive number 674b76ca311SAxel Dörfler; quadword start sector 675b76ca311SAxel Dörfler 676b76ca311SAxel Dörfler%if USE_TEST_MENU 677b76ca311SAxel Dörfler dw 0x06 678b76ca311SAxel Dörfler 679b76ca311SAxel Dörfler dw 2 680b76ca311SAxel Dörfler 681b76ca311SAxel Dörfler dw 5 682b76ca311SAxel Dörfler 683b76ca311SAxel Dörfler db 0x06 684b76ca311SAxel Dörfler db 'HAIKU', 0 685b76ca311SAxel Dörfler db 0x80 686b76ca311SAxel Dörfler dw 1, 0, 0, 0 687b76ca311SAxel Dörfler 688b76ca311SAxel Dörfler db 0x08 689b76ca311SAxel Dörfler db 'FreeBSD', 0 690b76ca311SAxel Dörfler db 0x80 691b76ca311SAxel Dörfler dw 0x003F, 0, 0, 0 692b76ca311SAxel Dörfler 693b76ca311SAxel Dörfler db 0x04 694b76ca311SAxel Dörfler db 'DOS', 0 695b76ca311SAxel Dörfler db 0x80 696b76ca311SAxel Dörfler dw 0x003E, 0, 0, 0 697b76ca311SAxel Dörfler 698b76ca311SAxel Dörfler db 0x06 699b76ca311SAxel Dörfler db 'LINUX', 0 700b76ca311SAxel Dörfler db 0x80 701b76ca311SAxel Dörfler dw 0x003F, 0, 0, 0 702b76ca311SAxel Dörfler 703b76ca311SAxel Dörfler db 0x08 704b76ca311SAxel Dörfler db 'BeOS R5', 0 705b76ca311SAxel Dörfler db 0x80 706b76ca311SAxel Dörfler dw 0x003F, 0, 0, 0 707b76ca311SAxel Dörfler 708b76ca311SAxel Dörfler db 0x07 709b76ca311SAxel Dörfler db 'OpenBSD', 0 710b76ca311SAxel Dörfler db 0x80 711b76ca311SAxel Dörfler dw 0xAAAA, 0, 0, 0 712b76ca311SAxel Dörfler 713b76ca311SAxel Dörfler dw kStage1UnusedSpace 714b76ca311SAxel Dörfler%endif 715b76ca311SAxel Dörfler 716