2 * Extended Boot Option ROM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Copyright IBM Corporation, 2007
19 * Authors: Anthony Liguori <aliguori@us.ibm.com>
27 .byte (_end - _start) / 512
31 /* setup ds so we can access the IVT */
35 /* there is one more bootable HD */
40 mov %eax, %cs:old_int19
42 /* install out int 19 handler */
43 movw $int19_handler, (0x19*4)
57 /* setup ds to access IVT */
69 1: /* hook int13: intb(0x404) == 1 */
70 /* save old int 13 to int 2c */
72 mov %eax, %cs:old_int13
74 /* install our int 13 handler */
75 movw $int13_handler, (0x13*4)
79 2: /* linux boot: intb(0x404) == 2 */
89 ljmp $0x9000 + 0x20, $0
91 3: /* fall through: inb(0x404) == 0 */
92 /* restore previous int $0x19 handler */
93 mov %cs:old_int19,%eax
103 #define FLAGS_CF 0x01
105 /* The two macro below clear/set the carry flag to indicate the status
106 * of the interrupt execution. It is not enough to issue a clc/stc instruction,
107 * since the value of the flags register will be overwritten by whatever is
113 /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
114 and $(~FLAGS_CF), 8(%bp)
120 /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
121 or $(FLAGS_CF), 8(%bp)
129 mov %sp, %bp /* remember the current stack position */
144 mov %sp, %bp /* remember the current stack position */
182 mov %ax, 0(%bx) /* ax */
183 mov 0(%bp), %ax /* bx */
185 mov %cx, 4(%bx) /* cx */
186 mov %dx, 6(%bx) /* dx */
187 mov %si, 8(%bx) /* si */
188 mov %ds, 10(%bx) /* ds */
189 mov %es, 12(%bx) /* ds */
190 movw \value, 14(%bx) /* value */
234 add32: /* lo, hi, lo, hi */
238 movw 4(%bp), %cx /* hi */
239 movw 6(%bp), %dx /* lo */
249 mul32: /* lo, hi, lo, hi */
250 /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */
259 /* for (i = 0; i < 16;) */
301 /* this really should be a function, not a macro but i'm lazy */
302 .macro read_write_disk_sectors cmd
313 /* save nb_sectors */
342 movw $0, 0(%bx) /* read c,h,s */
347 mov 6(%bx), %ax /* total_sectors */
348 mov 2(%bp), %si /* *= heads */
350 add 4(%bp), %ax /* += sectors - 1 */
352 push 4(%bx) /* total_heads */
354 push 6(%bx) /* total_sectors */
359 push 0(%bp) /* cylinders */
374 movw \cmd, 0(%bx) /* read */
375 movw 6(%bp), %ax /* nb_sectors */
377 movw %es, 4(%bx) /* segment */
378 movw 8(%bp), %ax /* offset */
380 movw %dx, 8(%bx) /* sector */
406 read_write_disk_sectors $0x01
409 read_write_disk_sectors $0x02
411 read_disk_drive_parameters:
414 /* allocate memory for packet, pointer gets returned in bx */
418 movw $0, 0(%bx) /* cmd = 0, read c,h,s */
423 /* normalize sector value */
428 /* normalize cylinders */
431 /* normalize heads */
459 /* do this last since it's the most sensitive */
463 alternate_disk_reset:
468 read_disk_drive_size:
472 movw $0, 0(%bx) /* cmd = 0, read c,h,s */
477 /* cylinders - 1 to cx:dx */
507 check_if_extensions_present:
514 .macro extended_read_write_sectors cmd
525 movw \cmd, 0(%bp) /* read */
526 movw 2(%si), %ax /* nb_sectors */
528 movw 4(%si), %ax /* offset */
530 movw 6(%si), %ax /* segment */
532 movw 8(%si), %ax /* block */
554 extended_read_sectors:
555 extended_read_write_sectors $0x01
557 extended_write_sectors:
558 extended_read_write_sectors $0x02
560 get_extended_drive_parameters:
568 movw $0, 0(%bp) /* read c,h,s */
597 /* set total number of sectors */
607 /* number of bytes per sector */
621 terminate_disk_emulation:
638 call read_disk_sectors
643 call read_disk_drive_parameters
648 call read_disk_drive_size
653 call check_if_extensions_present
658 call extended_read_sectors
663 call get_extended_drive_parameters
668 call terminate_disk_emulation
673 call alternate_disk_reset
678 call write_disk_sectors
683 call extended_write_sectors
686 int $0x18 /* boot failed */