GAS LISTING /tmp/cc2A9BiU.s 			page 1


   1              	# 1 "mbr.S"
   2              	# 1 "<built-in>"
   1              	/* -----------------------------------------------------------------------
   0              	
   0              	
   2              	 *
   3              	 *   Copyright 2007 H. Peter Anvin - All Rights Reserved
   4              	 *
   5              	 *   Permission is hereby granted, free of charge, to any person
   6              	 *   obtaining a copy of this software and associated documentation
   7              	 *   files (the "Software"), to deal in the Software without
   8              	 *   restriction, including without limitation the rights to use,
   9              	 *   copy, modify, merge, publish, distribute, sublicense, and/or
  10              	 *   sell copies of the Software, and to permit persons to whom
  11              	 *   the Software is furnished to do so, subject to the following
  12              	 *   conditions:
  13              	 *
  14              	 *   The above copyright notice and this permission notice shall
  15              	 *   be included in all copies or substantial portions of the Software.
  16              	 *
  17              	 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18              	 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19              	 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20              	 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21              	 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22              	 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23              	 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24              	 *   OTHER DEALINGS IN THE SOFTWARE.
  25              	 *
  26              	 * ----------------------------------------------------------------------- */
  27              	
  28              		.code16
  29              		.text
  30              	
  31              		.globl	bootsec
  32              	stack		= 0x7c00
  33              	driveno		= (stack-6)
  34              	sectors		= (stack-8)
  35              	secpercyl	= (stack-10)
  36              	
  37              	BIOS_page = 0x462
  38              	
  39              		/* gas/ld has issues with doing this as absolute addresses... */
  40              		.section ".bootsec", "a", @nobits
  41              		.globl	bootsec
  42              	bootsec:
  43 0000 00000000 		.space	512
  43      00000000 
  43      00000000 
  43      00000000 
  43      00000000 
  44              	
  45              		.text
  46              		.globl	_start
  47              	_start:
  48 0000 FA       		cli
  49 0001 31C0     		xorw	%ax, %ax
GAS LISTING /tmp/cc2A9BiU.s 			page 2


  50 0003 8ED8     		movw	%ax, %ds
  51 0005 8ED0     		movw	%ax, %ss
  52 0007 BC007C   		movw	$stack, %sp
  53 000a 89E6     		movw	%sp, %si
  54 000c 06       		pushw	%es		/* es:di -> $PnP header */
  55 000d 57       		pushw	%di
  56 000e 52       		pushw	%dx		/* dl -> drive number */
  57 000f 8EC0     		movw	%ax, %es
  58 0011 FB       		sti
  59 0012 FC       		cld
  60              	
  61              		/* Copy down to 0:0x600 */
  62 0013 BF0000   		movw	$_start, %di
  63 0016 B90001   		movw	$(512/2), %cx
  64 0019 F3A5     		rep; movsw
  65              	
  66 001b EA200000 		ljmpw	$0, $next
  66      00
  67              	
  68              	next:
  69              		/* Check to see if we have EBIOS */
  70 0020 52       		pushw	%dx		/* drive number */
  71 0021 B80041   		movw	$0x4100, %ax
  72 0024 BBAA55   		movw	$0x55aa, %bx
  73 0027 31C9     		xorw	%cx, %cx
  74 0029 30F6     		xorb	%dh, %dh
  75 002b F9       		stc
  76 002c CD13     		int	$0x13
  77 002e 7211     		jc	1f
  78 0030 81FB55AA 		cmpw	$0xaa55, %bx
  79 0034 750B     		jne	1f
  80 0036 F6C101   		testb	$0x01, %cl
  81 0039 7406     		jz	1f
  82              	
  83              		/* We have EBIOS; patch in a jump to read_sector_ebios */
  84 003b C7065F00 		movw	$0xeb+((read_sector_ebios-read_sector_cbios-2)<< 8), (read_sector_cbios)
  84      EB25
  85              	
  86              	1:
  87 0041 5A       		popw	%dx
  88              	
  89              		/* Get (C)HS geometry */
  90 0042 B408     		movb	$0x08, %ah
  91 0044 CD13     		int	$0x13
  92 0046 83E13F   		andw	$0x3f, %cx	/* Sector count */
  93 0049 51       		pushw	%cx		/* Save sectors on the stack */
  94 004a 31C0     		xorw	%ax, %ax
  95 004c 88F0     		movb	%dh, %al	/* dh = number of heads */
  96 004e 40       		incw	%ax		/* From 0-based to count */
  97 004f F7E1     		mulw	%cx		/* Heads*sectors -> sectors per cylinder */
  98 0051 50       		pushw	%ax		/* Save sectors/cylinder on the stack */
  99              	
 100 0052 6631C0   		xorl	%eax, %eax
 101 0055 6650     		pushl	%eax		/* Base */
 102 0057 6650     		pushl	%eax		/* Root */
 103 0059 E84F00   		call	scan_partition_table
 104              	
GAS LISTING /tmp/cc2A9BiU.s 			page 3


 105              		/* If we get here, we have no OS */
 106 005c E9D400   		jmp	missing_os
 107              	
 108              	/*
 109              	 * read_sector: read a single sector pointed to by %eax to 0x7c00.
 110              	 * CF is set on error.  All registers clobbered.
 111              	 */
 112              	read_sector:
 113              	read_sector_cbios:
 114 005f 6689C2   		movl	%eax, %edx
 115 0062 66C1EA10 		shrl	$16, %edx
 116 0066 F736F67B 		divw	(secpercyl)
 117 006a D0CC     		rorb	%ah
 118 006c D0CC     		rorb	%ah
 119 006e 88E1     		movb	%ah, %cl
 120 0070 88C5     		movb	%al, %ch
 121 0072 89D0     		movw	%dx, %ax
 122 0074 F636F87B 		divb	(sectors)
 123 0078 88C6     		movb	%al, %dh
 124 007a FEC4     		incb	%ah
 125 007c 08E1     		orb	%ah, %cl
 126 007e BB0000   		movw	$bootsec, %bx
 127 0081 B80102   		movw	$0x0201, %ax
 128 0084 EB09     		jmp	read_common
 129              	read_sector_ebios:
 130 0086 BEA801   		movw	$dapa, %si
 131 0089 66894408 		movl	%eax, 8(%si)
 132 008d B442     		movb	$0x42, %ah
 133              	read_common:
 134 008f 8A16FA7B 		movb	(driveno), %dl
 135 0093 CD13     		int	$0x13
 136 0095 C3       		ret
 137              	
 138              	/*
 139              	 * read_partition_table:
 140              	 *	Read a partition table (pointed to by %eax), and copy
 141              	 *	the partition table into the ptab buffer.
 142              	 *	Preserve registers.
 143              	 */
 144              	ptab	= _start+446
 145              	
 146              	read_partition_table:
 147 0096 6660     		pushal
 148 0098 E8C4FF   		call	read_sector
 149 009b 720B     		jc	20f
 150 009d BEBE01   		movw	$bootsec+446, %si
 151 00a0 BFBE01   		movw	$ptab, %di
 152 00a3 B92000   		movw	$(16*4/2), %cx
 153 00a6 F3A5     		rep ; movsw
 154              	20:
 155 00a8 6661     		popal
 156 00aa C3       		ret
 157              	
 158              	/*
 159              	 * scan_partition_table:
 160              	 *	Scan a partition table currently loaded in the partition table
 161              	 *	area.  Preserve 16-bit registers.
GAS LISTING /tmp/cc2A9BiU.s 			page 4


 162              	 *
 163              	 *	On stack:
 164              	 *	  18(%bp) - root (offset from MBR, or 0 for MBR)
 165              	 *	  22(%bp) - base (location of this partition table)
 166              	 */
 167              	
 168              	scan_partition_table:
 169 00ab 60       		pusha
 170 00ac 89E5     		movw	%sp, %bp
 171              	
 172              		/* Search for active partitions */
 173 00ae BFBE01   		movw	$ptab, %di
 174 00b1 B90400   		movw	$4, %cx
 175 00b4 31C0     		xorw	%ax, %ax
 176              	5:
 177 00b6 F60580   		testb	$0x80, (%di)
 178 00b9 7403     		jz 6f
 179 00bb 40       		incw	%ax
 180 00bc 89FE     		movw	%di, %si
 181              	6:
 182 00be 83C710   		addw	$16, %di
 183 00c1 E2F3     		loopw	5b
 184              	
 185 00c3 83F801   		cmpw	$1, %ax		/* Number of active partitions found */
 186 00c6 7446     		je	boot
 187 00c8 7773     		ja	too_many_active
 188              	
 189              		/* No active partitions found, look for extended partitions */
 190 00ca BFBE01   		movw	$ptab, %di
 191 00cd B104     		movb	$4, %cl		/* cx == 0 here */
 192              	7:
 193 00cf 8A4504   		movb	4(%di), %al
 194 00d2 3C05     		cmpb	$0x05, %al	/* MS-DOS extended */
 195 00d4 7408     		je	8f
 196 00d6 3C0F     		cmpb	$0x0f, %al	/* Win9x extended */
 197 00d8 7404     		je	8f
 198 00da 3C85     		cmpb	$0x85, %al	/* Linux extended */
 199 00dc 7529     		jne	9f
 200              	
 201              		/* It is an extended partition.  Read the extended partition and
 202              		   try to scan it.  If the scan returns, re-load the current
 203              		   partition table and resume scan. */
 204              	8:
 205 00de 668B4508 		movl	8(%di), %eax		/* Partition table offset */
 206 00e2 668B5612 		movl	18(%bp), %edx		/* "Root" */
 207 00e6 6601D0   		addl	%edx, %eax		/* Compute location of new ptab */
 208 00e9 6621D2   		andl	%edx, %edx		/* Is this the MBR? */
 209 00ec 7503     		jnz	10f
 210 00ee 6689C2   		movl	%eax, %edx		/* Offset -> root if this was MBR */
 211              	10:
 212 00f1 6650     		pushl	%eax			/* Push new base */
 213 00f3 6652     		pushl	%edx			/* Push new root */
 214 00f5 E89EFF   		call	read_partition_table
 215 00f8 7203     		jc 11f
 216 00fa E8AEFF   		call	scan_partition_table
 217              	11:
 218 00fd 83C408   		addw	$8, %sp
GAS LISTING /tmp/cc2A9BiU.s 			page 5


 219              		/* This returned, so we need to reload the current partition table */
 220 0100 668B4616 		movl	22(%bp), %eax
 221 0104 E88FFF   		call	read_partition_table
 222              	
 223              		/* fall through */
 224              	9:
 225              		/* Not an extended partition */
 226 0107 83C710   		addw	$16, %di
 227 010a E2C3     		loopw	7b
 228              	
 229              		/* Nothing found, return */
 230 010c 61       		popa
 231 010d C3       		ret
 232              	
 233              	/*
 234              	 * boot: invoke the actual bootstrap. (%si) points to the partition
 235              	 *	 table entry, and 22(%bp) has the partition table base.
 236              	 */
 237              	boot:
 238 010e 668B4408 		movl	8(%si), %eax
 239 0112 66034616 		addl	22(%bp), %eax
 240 0116 66894408 		movl	%eax, 8(%si)
 241 011a 56       		pushw	%si
 242 011b E841FF   		call	read_sector
 243 011e 5E       		popw	%si
 244 011f 7217     		jc	disk_error
 245 0121 813EFE01 		cmpw	$0xaa55, (bootsec+510)
 245      55AA
 246 0127 750A     		jne	missing_os		/* Not a valid boot sector */
 247 0129 BCFA7B   		movw	$driveno, %sp
 248 012c 5A       		popw	%dx		/* dl -> drive number */
 249 012d 5F       		popw	%di		/* es:di -> $PnP vector */
 250 012e 07       		popw	%es
 251 012f FA       		cli
 252 0130 E9FEFF   		jmp	bootsec
 253              	
 254              	/*
 255              	 * error messages
 256              	 */
 257              	missing_os:
 258 0133 BE5501   		movw	$missing_os_msg, %si
 259 0136 EB08     		jmp	error
 260              	disk_error:
 261 0138 BE6F01   		movw	$disk_error_msg, %si
 262 013b EB03     		jmp	error
 263              	too_many_active:
 264 013d BE8C01   		movw	$too_many_active_msg, %si
 265              		/* jmp error */
 266              	
 267              	error:
 268              	2:
 269 0140 AC       		lodsb
 270 0141 20C0     		andb	%al, %al
 271 0143 740C     		jz	3f
 272 0145 B40E     		movb	$0x0e, %ah
 273 0147 8A3E6204 		movb	(BIOS_page), %bh
 274 014b B307     		movb	$0x07, %bl
GAS LISTING /tmp/cc2A9BiU.s 			page 6


 275 014d CD10     		int	$0x10
 276 014f EBEF     		jmp	2b
 277              	3:
 278 0151 CD18     		int	$0x18		/* Boot failure */
 279 0153 EBFE     		jmp	.		/* Die */
 280              	
 281              	missing_os_msg:
 282 0155 4D697373 		.ascii	"Missing operating system."
 282      696E6720 
 282      6F706572 
 282      6174696E 
 282      67207379 
 283 016e 00       		.byte	0
 284              	disk_error_msg:
 285 016f 4F706572 		.ascii	"Operating system load error."
 285      6174696E 
 285      67207379 
 285      7374656D 
 285      206C6F61 
 286 018b 00       		.byte	0
 287              	too_many_active_msg:
 288 018c 4D756C74 		.ascii	"Multiple active partitions."
 288      69706C65 
 288      20616374 
 288      69766520 
 288      70617274 
 289 01a7 00       		.byte	0
 290              	
 291              		.balign	4
 292              	dapa:
 293 01a8 1000     		.short	16		/* Size of packet */
 294 01aa 0100     		.short	1		/* Sector count */
 295 01ac 007C     		.short	0x7c00		/* Buffer offset */
 296 01ae 0000     		.short	0		/* Buffer segment */
 297 01b0 00000000 		.long	0		/* LSW of LBA */
 298 01b4 00000000 		.long	0		/* MSW of LBA */
GAS LISTING /tmp/cc2A9BiU.s 			page 7


DEFINED SYMBOLS
                            *ABS*:0000000000000000 mbr.S
               mbr.S:42     .bootsec:0000000000000000 bootsec
               mbr.S:32     *ABS*:0000000000007c00 stack
               mbr.S:33     *ABS*:0000000000007bfa driveno
               mbr.S:34     *ABS*:0000000000007bf8 sectors
               mbr.S:35     *ABS*:0000000000007bf6 secpercyl
               mbr.S:37     *ABS*:0000000000000462 BIOS_page
               mbr.S:47     .text:0000000000000000 _start
               mbr.S:68     .text:0000000000000020 next
               mbr.S:129    .text:0000000000000086 read_sector_ebios
               mbr.S:113    .text:000000000000005f read_sector_cbios
               mbr.S:168    .text:00000000000000ab scan_partition_table
               mbr.S:257    .text:0000000000000133 missing_os
               mbr.S:112    .text:000000000000005f read_sector
               mbr.S:133    .text:000000000000008f read_common
               mbr.S:292    .text:00000000000001a8 dapa
               mbr.S:47     .text:00000000000001be ptab
               mbr.S:146    .text:0000000000000096 read_partition_table
               mbr.S:237    .text:000000000000010e boot
               mbr.S:263    .text:000000000000013d too_many_active
               mbr.S:260    .text:0000000000000138 disk_error
               mbr.S:281    .text:0000000000000155 missing_os_msg
               mbr.S:267    .text:0000000000000140 error
               mbr.S:284    .text:000000000000016f disk_error_msg
               mbr.S:287    .text:000000000000018c too_many_active_msg

NO UNDEFINED SYMBOLS
