1*4ed81583Skrw/* $OpenBSD: mbr.S,v 1.9 2022/09/02 07:46:03 krw Exp $ */ 2a47f7207Smickey 3a47f7207Smickey/* 4a47f7207Smickey * Copyright (c) 1997 Michael Shalayeff and Tobias Weingartner 5a47f7207Smickey * Copyright (c) 2003 Tom Cosgrove <tom.cosgrove@arches-consulting.com> 6a47f7207Smickey * All rights reserved. 7a47f7207Smickey * 8a47f7207Smickey * Redistribution and use in source and binary forms, with or without 9a47f7207Smickey * modification, are permitted provided that the following conditions 10a47f7207Smickey * are met: 11a47f7207Smickey * 1. Redistributions of source code must retain the above copyright 12a47f7207Smickey * notice, this list of conditions and the following disclaimer. 13a47f7207Smickey * 2. Redistributions in binary form must reproduce the above copyright 14a47f7207Smickey * notice, this list of conditions and the following disclaimer in the 15a47f7207Smickey * documentation and/or other materials provided with the distribution. 16a47f7207Smickey * 17a47f7207Smickey * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18a47f7207Smickey * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19a47f7207Smickey * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20a47f7207Smickey * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21a47f7207Smickey * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22a47f7207Smickey * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23a47f7207Smickey * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24a47f7207Smickey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25a47f7207Smickey * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26a47f7207Smickey * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27a47f7207Smickey * SUCH DAMAGE. 28a47f7207Smickey * 29a47f7207Smickey */ 30a47f7207Smickey/* Copyright (c) 1996 VaX#n8 (vax@linkdead.paranoia.com) 31a47f7207Smickey * last edited 9 July 1996 32a47f7207Smickey * many thanks to Erich Boleyn (erich@uruk.org) for putting up with 33a47f7207Smickey * all my questions, and for his work on GRUB 34a47f7207Smickey * You may use this code or fragments thereof in a manner consistent 35a47f7207Smickey * with the other copyrights as long as you retain my pseudonym and 36a47f7207Smickey * this copyright notice in the file. 37a47f7207Smickey */ 38a47f7207Smickey 39a47f7207Smickey .file "mbr.S" 40a47f7207Smickey 41a47f7207Smickey#include <machine/asm.h> 42a47f7207Smickey#include <assym.h> 43a47f7207Smickey 44a47f7207Smickey/* 45a47f7207Smickey * Memory layout: 46a47f7207Smickey * 47a47f7207Smickey * 0x07C00 -> 0x07DFF BIOS loads us here (at 31k) 48a47f7207Smickey * 0x07E00 -> 0x17BFC our stack (to 95k) 49a47f7207Smickey * 50a47f7207Smickey * 0x07A00 -> 0x07BFF we relocate to here (at 30k5) 51a47f7207Smickey * 52a47f7207Smickey * 0x07C00 -> 0x07DFF we load PBR here (at 31k) 53a47f7207Smickey * 54a47f7207Smickey * The BIOS loads us at physical address 0x07C00. We use a long jmp to 55a47f7207Smickey * normalise our address to seg:offset 07C0:0000. We then relocate to 56a47f7207Smickey * 0x07A00, seg:offset 07A0:0000. 57a47f7207Smickey * 58a47f7207Smickey * We use a long jmp to normalise our address to seg:offset 07A0:0000 59a47f7207Smickey * We set the stack to start at 07C0:FFFC (grows down on i386) 609676a180Stom * The partition boot record (PBR) loads /boot at seg:offset 4000:0000 61a47f7207Smickey */ 62a47f7207Smickey#define BOOTSEG 0x7c0 /* segment where we are loaded */ 63a47f7207Smickey#define BOOTRELOCSEG 0x7a0 /* segment where we relocate to */ 64a47f7207Smickey#define BOOTSTACKOFF 0xfffc /* stack starts here, grows down */ 65a47f7207Smickey#define PARTSZ 16 /* each partition table entry is 16 bytes */ 66a47f7207Smickey 67a47f7207Smickey#define CHAR_LBA_READ '.' 68a47f7207Smickey#define CHAR_CHS_READ ';' 69a47f7207Smickey 70a47f7207Smickey#ifdef DEBUG 71a47f7207Smickey#define CHAR_S 'S' /* started */ 72a47f7207Smickey#define CHAR_R 'R' /* relocated */ 73a47f7207Smickey#define CHAR_L 'L' /* looking for bootable partition */ 74a47f7207Smickey#define CHAR_B 'B' /* loading boot */ 75a47f7207Smickey#define CHAR_G 'G' /* jumping to boot */ 76a47f7207Smickey 77a47f7207Smickey#define DBGMSG(c) movb $c, %al; call Lchr 78a47f7207Smickey#else /* !DEBUG */ 79a47f7207Smickey#define DBGMSG(c) 80a47f7207Smickey#endif /* !DEBUG */ 81a47f7207Smickey 82a47f7207Smickey/* Clobbers %al - maybe more */ 83a47f7207Smickey#define putc(c) movb $c, %al; call Lchr 84a47f7207Smickey 85a47f7207Smickey/* Clobbers %esi - maybe more */ 86a47f7207Smickey#define puts(s) movw $s, %si; call Lmessage 87a47f7207Smickey 88a47f7207Smickey 89a47f7207Smickey .text 90a47f7207Smickey .code16 91a47f7207Smickey 92a47f7207Smickey .globl start 93a47f7207Smickeystart: 94a47f7207Smickey /* Adjust %cs to be right */ 95a47f7207Smickey ljmp $BOOTSEG, $1f 96a47f7207Smickey1: 97a47f7207Smickey /* Set up stack */ 98a47f7207Smickey movw %cs, %ax 99a47f7207Smickey 100a47f7207Smickey /* 101a47f7207Smickey * We don't need to disable and re-enable interrupts around the 102a47f7207Smickey * the load of ss and sp. 103a47f7207Smickey * 104a47f7207Smickey * From 80386 Programmer's Reference Manual: 105a47f7207Smickey * "A MOV into SS inhibits all interrupts until after the execution 106a47f7207Smickey * of the next instruction (which is presumably a MOV into eSP)" 107a47f7207Smickey * 108a47f7207Smickey * According to Hamarsoft's 86BUGS list (which is distributed with 109a47f7207Smickey * Ralph Brown's Interrupt List), some early 8086/88 processors 110a47f7207Smickey * failed to disable interrupts following a load into a segment 111a47f7207Smickey * register, but this was fixed with later steppings. 112a47f7207Smickey * 113a47f7207Smickey * Accordingly, this code will fail on very early 8086/88s, but 114a47f7207Smickey * nick@ will just have to live with it. Others will note that 1152a1e2e55Sdaniel * we require at least a Pentium compatible processor anyway. 116a47f7207Smickey */ 117a47f7207Smickey /* cli */ 118a47f7207Smickey movw %ax, %ss 119a47f7207Smickey movw $BOOTSTACKOFF, %sp 120a47f7207Smickey /* sti */ /* XXX not necessary; see above */ 121a47f7207Smickey 122a47f7207Smickey /* Set up data segment */ 123a47f7207Smickey movw %ax, %ds 124a47f7207Smickey DBGMSG(CHAR_S) 125a47f7207Smickey 126a47f7207Smickey /* 127a47f7207Smickey * On the PC architecture, the boot record (originally on a floppy 128a47f7207Smickey * disk) is loaded at 0000:7C00 (hex) and execution starts at the 129a47f7207Smickey * beginning. 130a47f7207Smickey * 131a47f7207Smickey * When hard disk support was added, a scheme to partition disks into 132a47f7207Smickey * four separate partitions was used, to allow multiple operating 133a47f7207Smickey * systems to be installed on the one disk. The boot sectors of the 134a47f7207Smickey * operating systems on each partition would of course expect to be 135a47f7207Smickey * loaded at 0000:7C00. 136a47f7207Smickey * 137a47f7207Smickey * The first sector of the hard disk is the master boot record (MBR). 138a47f7207Smickey * It is this which defines the partitions and says which one is 139a47f7207Smickey * bootable. Of course, the BIOS loads the MBR at 0000:7C00, the 140a47f7207Smickey * same location where the MBR needs to load the partition boot 141a47f7207Smickey * record (PBR, called biosboot in OpenBSD). 142a47f7207Smickey * 143a47f7207Smickey * Therefore, the MBR needs to relocate itself before loading the PBR. 144a47f7207Smickey * 145a47f7207Smickey * Make it so. 146a47f7207Smickey */ 147a47f7207Smickey movw $BOOTRELOCSEG, %ax 148a47f7207Smickey movw %ax, %es 149a47f7207Smickey xorw %si, %si 150a47f7207Smickey xorw %di, %di 151a47f7207Smickey movw $0x200, %cx /* Bytes in MBR, relocate it all */ 152a47f7207Smickey cld 153a47f7207Smickey rep 154a47f7207Smickey movsb 155a47f7207Smickey 156a47f7207Smickey /* Jump to relocated self */ 157a47f7207Smickey ljmp $BOOTRELOCSEG, $reloc 158a47f7207Smickeyreloc: 159a47f7207Smickey DBGMSG(CHAR_R) 160a47f7207Smickey 161a47f7207Smickey /* Set up %es and %ds */ 162a47f7207Smickey pushw %ds 163a47f7207Smickey popw %es /* next boot is at the same place as we were loaded */ 164a47f7207Smickey pushw %cs 165a47f7207Smickey popw %ds /* and %ds is at the %cs */ 166a47f7207Smickey 167a47f7207Smickey#ifdef SERIAL 168a47f7207Smickey /* Initialize the serial port to 9600 baud, 8N1. 169a47f7207Smickey */ 170bd4e04c6Smglocker pushw %dx 171a47f7207Smickey xorw %ax, %ax 172a47f7207Smickey movb $0xe3, %ax 173a47f7207Smickey movw $SERIAL, %dx 174a47f7207Smickey int $0x14 175bd4e04c6Smglocker popw %dx 176a47f7207Smickey#endif 177a47f7207Smickey 178a47f7207Smickey /* BIOS passes us drive number in %dl 179a47f7207Smickey * 180a47f7207Smickey * XXX - This is not always true. We currently check if %dl 181a47f7207Smickey * points to a HD, and if not we complain, and set it to point 182a47f7207Smickey * to the first HDD. Note, this is not 100% correct, since 183ef9decb1Stom * there is a possibility that you boot from HD #2, and still 184a47f7207Smickey * get (%dl & 0x80) == 0x00, these type of systems will lose. 185a47f7207Smickey */ 186a47f7207Smickey testb $0x80, %dl 187a47f7207Smickey jnz drive_ok 188a47f7207Smickey 189a47f7207Smickey /* MBR on floppy or old BIOS 190a47f7207Smickey * Note: MBR (this code) should never be on a floppy. It does 191a47f7207Smickey * not belong there, so %dl should never be 0x00. 192a47f7207Smickey * 193a47f7207Smickey * Here we simply complain (should we?), and then hardcode the 194a47f7207Smickey * boot drive to 0x80. 195a47f7207Smickey */ 196a47f7207Smickey puts(efdmbr) 197a47f7207Smickey 198a47f7207Smickey /* If we are passed bogus data, set it to HD #1 199a47f7207Smickey */ 200a47f7207Smickey movb $0x80, %dl 201a47f7207Smickey 202a47f7207Smickeydrive_ok: 203a47f7207Smickey /* Find the first active partition. 204a47f7207Smickey * Note: this should be the only active partition. We currently 205a47f7207Smickey * don't check for that. 206a47f7207Smickey */ 207a47f7207Smickey movw $pt, %si 208a47f7207Smickey 209a47f7207Smickey movw $NDOSPART, %cx 210a47f7207Smickeyfind_active: 211a47f7207Smickey DBGMSG(CHAR_L) 212a47f7207Smickey movb (%si), %al 213a47f7207Smickey 214a47f7207Smickey cmpb $DOSACTIVE, %al 215a47f7207Smickey je found 216a47f7207Smickey 217a47f7207Smickey addw $PARTSZ, %si 218a47f7207Smickey loop find_active 219a47f7207Smickey 220a47f7207Smickey /* No bootable partition */ 221a47f7207Smickeyno_part: 222a47f7207Smickey movw $enoboot, %si 223a47f7207Smickey 224a47f7207Smickeyerr_stop: 225a47f7207Smickey call Lmessage 226a47f7207Smickey 227a47f7207Smickeystay_stopped: 2289676a180Stom sti /* Ensure Ctl-Alt-Del will work */ 229a47f7207Smickey hlt 230a47f7207Smickey /* Just to make sure */ 231a47f7207Smickey jmp stay_stopped 232a47f7207Smickey 233a47f7207Smickeyfound: 234a47f7207Smickey /* 235a47f7207Smickey * Found bootable partition 236a47f7207Smickey */ 237a47f7207Smickey 238a47f7207Smickey DBGMSG(CHAR_B) 239a47f7207Smickey 240a47f7207Smickey /* Store the drive number (from %dl) in decimal */ 241a47f7207Smickey movb %dl, %al 242a47f7207Smickey andb $0x0F, %al 243a47f7207Smickey addb $'0', %al 244a47f7207Smickey movb %al, drive_num 245a47f7207Smickey 246a47f7207Smickey /* 247a47f7207Smickey * Store the partition number, in decimal. 248a47f7207Smickey * 249a47f7207Smickey * We started with cx = 4; if found we want part '0' 250a47f7207Smickey * cx = 3; part '1' 251a47f7207Smickey * cx = 2; part '2' 252a47f7207Smickey * cx = 1; part '3' 253a47f7207Smickey * 254a47f7207Smickey * We'll come into this with no other values for cl. 255a47f7207Smickey */ 256a47f7207Smickey movb $'0'+4, %al 257a47f7207Smickey subb %cl, %al 258a47f7207Smickey movb %al, part_num 259a47f7207Smickey 260a47f7207Smickey /* 261a47f7207Smickey * Tell operator what partition we're trying to boot. 262a47f7207Smickey * 263a47f7207Smickey * Using drive X, partition Y 264a47f7207Smickey * - this used to be printed out after successfully loading the 265a47f7207Smickey * partition boot record; we now print it out before 266a47f7207Smickey */ 267a47f7207Smickey pushw %si 268a47f7207Smickey movw $info, %si 269a47f7207Smickey call Lmessage 270a47f7207Smickey popw %si 271a47f7207Smickey 272a47f7207Smickey /* 273a47f7207Smickey * Partition table entry format: 274a47f7207Smickey * 275a47f7207Smickey * 0x00 BYTE boot indicator (0x80 = active, 0x00 = inactive) 276a47f7207Smickey * 0x01 BYTE start head 277a47f7207Smickey * 0x02 WORD start cylinder, sector 278a47f7207Smickey * 0x04 BYTE system type (0xA6 = OpenBSD) 279a47f7207Smickey * 0x05 BYTE end head 280a47f7207Smickey * 0x06 WORD end cylinder, sector 281a47f7207Smickey * 0x08 LONG start LBA sector 282a47f7207Smickey * 0x0C LONG number of sectors in partition 283a47f7207Smickey * 284a47f7207Smickey * In the case of a partition that extends beyond the 8GB boundary, 285a47f7207Smickey * the LBA values will be correct, the CHS values will have their 286a47f7207Smickey * maximums (typically (C,H,S) = (1023,255,63)). 287a47f7207Smickey * 288a47f7207Smickey * %ds:%si points to the active partition table entry. 289a47f7207Smickey */ 290a47f7207Smickey 291a47f7207Smickey /* We will load the partition boot sector (biosboot) where we 292a47f7207Smickey * were originally loaded. We'll check to make sure something 293a47f7207Smickey * valid comes in. So that we don't find ourselves, zero out 294a47f7207Smickey * the signature at the end. 295a47f7207Smickey */ 296a47f7207Smickey movw $0, %es:signature(,1) 297a47f7207Smickey 298a47f7207Smickey /* 299a47f7207Smickey * We will use the LBA sector number if we have LBA support, 300a47f7207Smickey * so find out. 301a47f7207Smickey */ 302a47f7207Smickey 303a47f7207Smickey /* 304a47f7207Smickey * BIOS call "INT 0x13 Extensions Installation Check" 305a47f7207Smickey * Call with %ah = 0x41 306a47f7207Smickey * %bx = 0x55AA 307a47f7207Smickey * %dl = drive (0x80 for 1st hd, 0x81 for 2nd, etc) 308a47f7207Smickey * Return: 309a47f7207Smickey * carry set: failure 310a47f7207Smickey * %ah = error code (0x01, invalid func) 311a47f7207Smickey * carry clear: success 312a47f7207Smickey * %bx = 0xAA55 (must verify) 313a47f7207Smickey * %ah = major version of extensions 314a47f7207Smickey * %al (internal use) 315a47f7207Smickey * %cx = capabilities bitmap 316a47f7207Smickey * 0x0001 - extnd disk access funcs 317a47f7207Smickey * 0x0002 - rem. drive ctrl funcs 318a47f7207Smickey * 0x0004 - EDD functions with EBP 319a47f7207Smickey * %dx (extension version?) 320a47f7207Smickey */ 321a47f7207Smickey 322a47f7207Smickey movb %dl, (%si) /* Store drive here temporarily */ 323a47f7207Smickey /* (This call trashes %dl) */ 324a47f7207Smickey /* 325a47f7207Smickey * XXX This is actually the correct 326a47f7207Smickey * place to store this. The 0x80 327a47f7207Smickey * value used to indicate the 328a47f7207Smickey * active partition is by intention 329a47f7207Smickey * the same as the BIOS drive value 330a47f7207Smickey * for the first hard disk (0x80). 331a47f7207Smickey * At one point, 0x81 would go here 332a47f7207Smickey * for the second hard disk; the 333a47f7207Smickey * 0x80 value is often used as a 334a47f7207Smickey * bit flag for testing, rather 335a47f7207Smickey * than an exact byte value. 336a47f7207Smickey */ 337a47f7207Smickey movw $0x55AA, %bx 338a47f7207Smickey movb $0x41, %ah 339a47f7207Smickey int $0x13 340a47f7207Smickey 341a47f7207Smickey movb (%si), %dl /* Get back drive number */ 342a47f7207Smickey 343a47f7207Smickey jc do_chs /* Did the command work? Jump if not */ 344a47f7207Smickey cmpw $0xAA55, %bx /* Check that bl, bh exchanged */ 345a47f7207Smickey jne do_chs /* If not, don't have EDD extensions */ 346a47f7207Smickey testb $0x01, %cl /* And do we have "read" available? */ 347a47f7207Smickey jz do_chs /* Again, use CHS if not */ 348a47f7207Smickey 349a47f7207Smickeydo_lba: 350a47f7207Smickey /* 351a47f7207Smickey * BIOS call "INT 0x13 Extensions Extended Read" 352a47f7207Smickey * Call with %ah = 0x42 353a47f7207Smickey * %dl = drive (0x80 for 1st hd, 0x81 for 2nd, etc) 354a47f7207Smickey * %ds:%si = segment:offset of command packet 355a47f7207Smickey * Return: 356a47f7207Smickey * carry set: failure 357a47f7207Smickey * %ah = error code (0x01, invalid func) 358a47f7207Smickey * command packet's sector count field set 359a47f7207Smickey * to the number of sectors successfully 360a47f7207Smickey * transferred 361a47f7207Smickey * carry clear: success 362a47f7207Smickey * %ah = 0 (success) 363a47f7207Smickey * Command Packet: 364a47f7207Smickey * 0x0000 BYTE packet size (0x10 or 0x18) 365a47f7207Smickey * 0x0001 BYTE reserved (should be 0) 366a47f7207Smickey * 0x0002 WORD sectors to transfer (max 127) 367a47f7207Smickey * 0x0004 DWORD seg:offset of transfer buffer 368a47f7207Smickey * 0x0008 QWORD starting sector number 369a47f7207Smickey */ 370a47f7207Smickey movb $CHAR_LBA_READ, %al 371a47f7207Smickey call Lchr 372a47f7207Smickey 373a47f7207Smickey /* Load LBA sector number from active partition table entry */ 374a47f7207Smickey movl 8(%si), %ecx 375a47f7207Smickey movl %ecx, lba_sector 376a47f7207Smickey 377a47f7207Smickey pushw %si /* We'll need %si later */ 378a47f7207Smickey 379a47f7207Smickey movb $0x42, %ah 380a47f7207Smickey movw $lba_command, %si 381a47f7207Smickey int $0x13 382a47f7207Smickey 38351249ee3Sderaadt popw %si /* get back %si */ 384a47f7207Smickey 385a47f7207Smickey jnc booting_os /* If it worked, run the pbr we got */ 386a47f7207Smickey 387a47f7207Smickey /* 388a47f7207Smickey * LBA read failed, fall through to try CHS read 389a47f7207Smickey */ 390a47f7207Smickey 391a47f7207Smickeydo_chs: 392a47f7207Smickey /* 393a47f7207Smickey * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into 394a47f7207Smickey * memory 395a47f7207Smickey * Call with %ah = 0x2 396a47f7207Smickey * %al = number of sectors 397a47f7207Smickey * %ch = cylinder & 0xFF 398a47f7207Smickey * %cl = sector (0-63) | rest of cylinder bits 399a47f7207Smickey * %dh = head 400a47f7207Smickey * %dl = drive (0x80 for hard disk) 401a47f7207Smickey * %es:%bx = segment:offset of buffer 402a47f7207Smickey * Return: 403a47f7207Smickey * carry set: failure 404a47f7207Smickey * %ah = err code 405a47f7207Smickey * %al = number of sectors transferred 406a47f7207Smickey * carry clear: success 407a47f7207Smickey * %al = 0x0 OR number of sectors transferred 408a47f7207Smickey * (depends on BIOS!) 409a47f7207Smickey * (according to Ralph Brown Int List) 410a47f7207Smickey */ 411a47f7207Smickey movb $CHAR_CHS_READ, %al 412a47f7207Smickey call Lchr 413a47f7207Smickey 414a47f7207Smickey /* Load values from active partition table entry */ 415a47f7207Smickey movb 1(%si), %dh /* head */ 416a47f7207Smickey movw 2(%si), %cx /* sect, cyl */ 417a47f7207Smickey movw $0x201, %ax /* function and number of blocks */ 418a47f7207Smickey xorw %bx, %bx /* put it at %es:0 */ 419a47f7207Smickey int $0x13 420a47f7207Smickey jnc booting_os 421a47f7207Smickey 422a47f7207Smickeyread_error: 423a47f7207Smickey movw $eread, %si 424a47f7207Smickey jmp err_stop 425a47f7207Smickey 426a47f7207Smickeybooting_os: 427a47f7207Smickey puts(crlf) 428a47f7207Smickey DBGMSG(CHAR_G) 429a47f7207Smickey 430a47f7207Smickey /* 431a47f7207Smickey * Make sure the pbr we loaded has a valid signature at the end. 432a47f7207Smickey * This also ensures that something did load where we were expecting 433a47f7207Smickey * it, as there's still a copy of our code there... 434a47f7207Smickey */ 435a47f7207Smickey cmpw $DOSMBR_SIGNATURE, %es:signature(,1) 436a47f7207Smickey jne missing_os 437a47f7207Smickey 438a47f7207Smickey /* jump to the new code (%ds:%si is at the right point) */ 439a47f7207Smickey ljmp $0, $BOOTSEG << 4 440a47f7207Smickey /* not reached */ 441a47f7207Smickey 442a47f7207Smickeymissing_os: 443a47f7207Smickey movw $enoos, %si 444a47f7207Smickey jmp err_stop 445a47f7207Smickey 446a47f7207Smickey/* 447a47f7207Smickey * Display string 448a47f7207Smickey */ 449a47f7207SmickeyLmessage: 450a47f7207Smickey pushw %ax 451a47f7207Smickey cld 452a47f7207Smickey1: 453a47f7207Smickey lodsb /* %al = *%si++ */ 454a47f7207Smickey testb %al, %al 455a47f7207Smickey jz 1f 456a47f7207Smickey call Lchr 457a47f7207Smickey jmp 1b 458a47f7207Smickey 459a47f7207Smickey/* 460a47f7207Smickey * Lchr: write the error message in %ds:%si to console 461a47f7207Smickey */ 462a47f7207SmickeyLchr: 463a47f7207Smickey pushw %ax 464a47f7207Smickey 465a47f7207Smickey#ifdef SERIAL 466a47f7207Smickey pushw %dx 467a47f7207Smickey movb $0x01, %ah 468bd4e04c6Smglocker movw $SERIAL, %dx 469a47f7207Smickey int $0x14 470a47f7207Smickey popw %dx 471a47f7207Smickey#else 472a47f7207Smickey pushw %bx 473a47f7207Smickey movb $0x0e, %ah 474a47f7207Smickey movw $1, %bx 475a47f7207Smickey int $0x10 476a47f7207Smickey popw %bx 477a47f7207Smickey#endif 478a47f7207Smickey1: popw %ax 479a47f7207Smickey ret 480a47f7207Smickey 481a47f7207Smickey/* command packet for LBA read of boot sector */ 482a47f7207Smickeylba_command: 483a47f7207Smickey .byte 0x10 /* size of command packet */ 484a47f7207Smickey .byte 0x00 /* reserved */ 485a47f7207Smickey .word 0x0001 /* sectors to transfer, just 1 */ 486a47f7207Smickey .word 0 /* target buffer, offset */ 487a47f7207Smickey .word BOOTSEG /* target buffer, segment */ 488a47f7207Smickeylba_sector: 489a47f7207Smickey .long 0, 0 /* sector number */ 490a47f7207Smickey 491a47f7207Smickey/* Info messages */ 49251249ee3Sderaadtinfo: .ascii "Using drive " 493a47f7207Smickeydrive_num: 494a47f7207Smickey .byte 'X' 495a47f7207Smickey .ascii ", partition " 496a47f7207Smickeypart_num: 497a47f7207Smickey .asciz "Y" 498a47f7207Smickey 499a47f7207Smickey/* Error messages */ 500a47f7207Smickeyefdmbr: .asciz "MBR on floppy or old BIOS\r\n" 501a47f7207Smickeyeread: .asciz "\r\nRead error\r\n" 502a47f7207Smickeyenoos: .asciz "No O/S\r\n" 503a47f7207Smickeyenoboot: .ascii "No active partition" /* runs into crlf... */ 504a47f7207Smickeycrlf: .asciz "\r\n" 505a47f7207Smickey 506a47f7207Smickeyendofcode: 507a47f7207Smickey nop 508a47f7207Smickey 509a47f7207Smickey/* (MBR) NT disk signature offset */ 510a47f7207Smickey . = 0x1b8 511a47f7207Smickey .space 4, 0 512a47f7207Smickey 513a47f7207Smickey/* partition table */ 514a47f7207Smickey/* flag, head, sec, cyl, type, ehead, esect, ecyl, start, len */ 515a47f7207Smickey . = DOSPARTOFF /* starting address of partition table */ 516*4ed81583Skrwpt: .fill 0x40,1,0 517a47f7207Smickey/* the last 2 bytes in the sector 0 contain the signature */ 518a47f7207Smickey . = 0x1fe 519a47f7207Smickeysignature: 520a47f7207Smickey .short DOSMBR_SIGNATURE 521a47f7207Smickey . = 0x200 522