1 /* ----------------------------------------------------------------------- 2 * 3 * Copyright 2010-2011 Gene Cumm 4 * 5 * Portions from mbr.S: 6 * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved 7 * Copyright 2009 Intel Corporation; author: H. Peter Anvin 8 * 9 * Permission is hereby granted, free of charge, to any person 10 * obtaining a copy of this software and associated documentation 11 * files (the "Software"), to deal in the Software without 12 * restriction, including without limitation the rights to use, 13 * copy, modify, merge, publish, distribute, sublicense, and/or 14 * sell copies of the Software, and to permit persons to whom 15 * the Software is furnished to do so, subject to the following 16 * conditions: 17 * 18 * The above copyright notice and this permission notice shall 19 * be included in all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 * OTHER DEALINGS IN THE SOFTWARE. 29 * 30 * ----------------------------------------------------------------------- */ 31 32 /* 33 * handoff.S: MBR/VBR-like codeblock to display handoff data 34 * 35 * Displays the values of DL, DS, SI, the contents of [DS:SI] (16 bytes), 36 * the values of ES, DI, the contents of [ES:DI] (4 bytes), scans memory for 37 * $PnP then reports a boot failure. 38 * 39 * This should (hopefully) be only 8086 code 40 */ 41 42 /* 43 * Install instructions (assuming your target is /dev/dev; file or block device): 44 * 45 * MBR: 46 * dd conv=notrunc bs=440 count=1 if=handoff.bin of=/dev/dev 47 * 48 * VBR/PBR (should work for FAT12/16/32, ext[234]fs, btrfs): 49 * echo -en "\0353\0130\0220" |dd conv=notrunc bs=1 count=3 of=/dev/dev 50 * dd conv=notrunc bs=2 count=210 seek=45 if=handoff.bin of=/dev/dev 51 */ 52 53 // #define DEBUG_MARKER1 /* Insert markers in binary */ 54 // #define DEBUG_START /* Print entry addresses at start */ 55 // #define DEBUG_LOADE /* movw versus pop */ 56 #define DEBUG_PNP /* Scan for $PnP and show address */ 57 #define DEBUG_PAK /* Press Any Key before boot fail */ 58 // #define DEBUG_ENTRY_REG /* Store (manually as pusha is 80186) registers */ 59 // #define DEBUG_FDT /* Print the floppy descriptor table; INT 1Eh*/ 60 61 #ifdef DEBUG_MARKER1 62 .macro ASCII_MARKER1 s:vararg 63 .ascii \s 64 .endm 65 #else /* DEBUG_MARKER1 */ 66 .macro ASCII_MARKER1 s:vararg 67 .endm 68 #endif /* DEBUG_MARKER1 */ 69 70 #ifdef DEBUG_LOADE 71 .macro LOADE r:req, t:req 72 movw (es_\r), %\t 73 .endm 74 #else /* DEBUG_LOADE */ 75 .macro LOADE r:req, t:req 76 popw %\t 77 .endm 78 #endif /* DEBUG_LOADE */ 79 80 .code16 81 .text 82 83 entry = 0x7c00 84 stack = (entry) 85 e_start = (stack) 86 e_ax = (e_start-2) 87 e_ss = (e_ax-2) 88 e_sp = (e_ss-2) 89 e_bot = (e_ss) 90 /* Doubtful this will be used */ 91 e0_beg = (e_bot) 92 e0_ax = (e0_beg-2) 93 e0_cx = (e0_ax-2) 94 e0_dx = (e0_cx-2) 95 e0_bx = (e0_dx-2) 96 e0_sp = (e0_bx-2) 97 e0_bp = (e0_sp-2) 98 e0_si = (e0_bp-2) 99 e0_di = (e0_si-2) 100 e0_ds = (e0_di-2) 101 e0_es = (e0_ds-2) 102 e0_bot = (e0_es) 103 es_beg = (e0_bot) /* Original register values from entry point */ 104 es_di = (es_beg-2) 105 es_es = (es_di-2) 106 es_si = (es_es-2) 107 es_ds = (es_si-2) 108 es_bot = (es_ds) 109 110 BIOS_page = 0x462 111 112 int_1e = (4*0x1e) 113 int_1e_seg = (int_1e) 114 int_1e_off = (int_1e+2) 115 116 .globl _start 117 _start: 118 cli 119 #ifdef DEBUG_ENTRY_REG 120 movw %ax, e_ax 121 movw %ss, e_ss 122 movw %sp, e_sp 123 #endif /* DEBUG_ENTRY_REG */ 124 xorw %ax, %ax 125 movw %ax, %ss 126 #ifdef DEBUG_ENTRY_REG 127 movw $e0_beg, %sp 128 /* pushaw */ /* 80186 */ 129 pushw %ax 130 pushw %cx 131 pushw %dx 132 pushw %bx 133 pushw %sp 134 pushw %bp 135 pushw %si 136 pushw %di 137 pushw %ds 138 pushw %es 139 #else /* DEBUG_ENTRY_REG */ 140 movw $es_beg, %sp 141 #endif /* DEBUG_ENTRY_REG */ 142 pushw %di /* es:di -> $PnP header */ 143 pushw %es 144 pushw %si 145 pushw %ds 146 sti 147 cld 148 pushw %cs 149 popw %ds 150 151 #ifdef DEBUG_START 152 pushw %dx 153 call crlf 154 movw $(_start),%dx /* 0x0600 mbr.ld .text address */ 155 call wrhexw 156 call crlf 157 call caddr 158 caddr: 159 popw %dx 160 subw $(caddr - _start), %dx 161 call wrhexw 162 call crlf 163 popw %dx 164 #endif /* DEBUG_START */ 165 166 /* write DL */ 167 pr_dl: call wrstr 168 .ascii "DL: \0" 169 call wrhexb 170 /* DS */ 171 pr_ds: call wrstr 172 .ascii " DS: \0" 173 LOADE ds, dx 174 pushw %dx 175 popw %es 176 call wrhexw 177 /* SI */ 178 pr_si: call wrstr 179 .ascii " SI: \0" 180 LOADE si, dx 181 pushw %dx 182 popw %di 183 call wrhexw 184 call crlf 185 /* DS:SI */ 186 movw $16, %cx 187 call wrhexbses 188 call crlf 189 190 /* ES */ 191 pr_es: call wrstr 192 .ascii "ES: \0" 193 LOADE es, dx 194 pushw %dx 195 popw %es 196 call wrhexw 197 pr_di: call wrstr 198 .ascii " DI: \0" 199 LOADE di, dx 200 pushw %dx 201 popw %di 202 call wrhexw 203 call crlf 204 /* ES:DI */ /* %es:0(%di) */ 205 movw $4, %cx 206 call wrhexbses 207 208 #ifdef DEBUG_PNP 209 subw $4, %si 210 es lodsw 211 cmpw $0x5024, %ax 212 jne scn_pnp 213 es lodsw 214 cmpw $0x506E, %ax 215 jne scn_pnp 216 call wrstr 217 .ascii " =$PnP\0" 218 scn_pnp: 219 call crlf 220 /* $PnP Scan */ 221 movw $0xf000, %dx 222 pushw %dx 223 popw %es 224 movw $0, %si 225 movw $0x1000, %cx 226 /* 0x506E5024 */ 227 movw $0x5024, %dx 228 movw $0x506E, %bx 229 ch_pnp: es lodsw /* Check for $PnP */ 230 cmpw %dx, %ax 231 jne ch_pnp_l 232 es lodsw 233 cmpw %bx, %ax 234 je pr_pnp 235 ch_pnp_l: /* Check $PnP failed; loop to next address */ 236 addw $14, %si 237 andw $0xFFF0, %si 238 loopw ch_pnp 239 jmp pnp_end 240 pr_pnp: 241 pushw %si 242 call wrstr 243 .ascii "$PnP-\0" 244 movw %es, %dx 245 call wrhexw 246 movb $':, %al 247 call wrchr 248 popw %dx 249 andw $0xFFF0, %dx 250 call wrhexw 251 #endif /* DEBUG_PNP */ 252 call crlf 253 pnp_end: 254 255 #ifdef DEBUG_FDT 256 /* INT 1Eh: Floppy Parameter Table Pointer */ 257 pr_1e: call wrstr 258 .ascii "INT 1Eh: \0" 259 mov $int_1e,%bx 260 les (%bx),%di 261 pushw %es 262 popw %dx 263 call wrhexw 264 movb $':, %al 265 call wrchr 266 pushw %di 267 popw %dx 268 call wrhexw 269 call crlf 270 /* [INT 1Eh] */ 271 movw $14, %cx 272 call wrhexbses 273 call crlf 274 #endif /* DEBUG_FDT */ 275 276 end: 277 jmp bootfail 278 279 ASCII_MARKER1 "wc" 280 wrchr: 281 movb $0x0e, %ah 282 movb (BIOS_page), %bh 283 movb $0x07, %bl 284 int $0x10 /* May destroy %bp */ 285 ret 286 287 ASCII_MARKER1 "ws" 288 wrstr: 289 pop %si 290 wrstr_l: 291 lodsb 292 cmpb $0, %al 293 je wrstr_d 294 call wrchr 295 jmp wrstr_l 296 wrstr_d: 297 push %si 298 ret 299 300 crlf: 301 call wrstr 302 .ascii "\r\n\0" 303 ret 304 305 ASCII_MARKER1 "hx" 306 wrhexn: 307 and $0x0F, %al 308 cmpb $10, %al 309 jae .alph 310 addb $'0, %al 311 jmp .wc 312 .alph: 313 addb $('A - 10), %al 314 .wc: 315 call wrchr 316 ret 317 318 wrhexb: 319 pushw %cx 320 movb %dl, %al 321 pushw %ax 322 movb $4, %cl 323 rorw %cl, %ax 324 call wrhexn 325 popw %ax 326 call wrhexn 327 popw %cx 328 ret 329 330 wrhexw: 331 pushw %cx 332 movb $8, %cl 333 rorw %cl, %dx 334 call wrhexb 335 rorw %cl, %dx 336 call wrhexb 337 popw %cx 338 ret 339 340 ASCII_MARKER1 "HE" 341 wrhexbses: 342 pushw %di 343 popw %si 344 wrhexbses_l: 345 movb $' , %al 346 call wrchr 347 es lodsb 348 movw %ax, %dx 349 call wrhexb 350 loop wrhexbses_l 351 ret 352 353 data: 354 ASCII_MARKER1 "bf" 355 bootfail: 356 #ifdef DEBUG_PAK 357 call wrstr 358 .ascii "\r\n\r\nPress any key\r\n\0" 359 xor %ax, %ax 360 int $0x16 361 #endif 362 int $0x18 /* Boot failure */ 363 die: 364 hlt 365 jmp die 366