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>
22 #define OLD_INT19 (0x80 * 4) /* re-use INT 0x80 BASIC vector */
23 #define OLD_INT13 (0x81 * 4) /* re-use INT 0x81 BASIC vector */
30 .byte (_end - _start) / 512
34 /* setup ds so we can access the IVT */
38 /* there is one more bootable HD */
45 /* install out int 19 handler */
46 movw $int19_handler, (0x19*4)
54 push %eax /* reserve space for lret */
61 /* setup ds to access IVT */
65 /* save old int 13 to int 2c */
69 /* install our int 13 handler */
70 movw $int13_handler, (0x13*4)
73 /* restore previous int $0x19 handler */
77 /* write old handler as return address onto stack */
92 /* The two macro below clear/set the carry flag to indicate the status
93 * of the interrupt execution. It is not enough to issue a clc/stc instruction,
94 * since the value of the flags register will be overwritten by whatever is
100 /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
101 and $(~FLAGS_CF), 8(%bp)
107 /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
108 or $(FLAGS_CF), 8(%bp)
116 mov %sp, %bp /* remember the current stack position */
131 mov %sp, %bp /* remember the current stack position */
169 mov %ax, 0(%bx) /* ax */
170 mov 0(%bp), %ax /* bx */
172 mov %cx, 4(%bx) /* cx */
173 mov %dx, 6(%bx) /* dx */
174 mov %si, 8(%bx) /* si */
175 mov %ds, 10(%bx) /* ds */
176 mov %es, 12(%bx) /* ds */
177 movw \value, 14(%bx) /* value */
221 add32: /* lo, hi, lo, hi */
225 movw 4(%bp), %cx /* hi */
226 movw 6(%bp), %dx /* lo */
236 mul32: /* lo, hi, lo, hi */
237 /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */
246 /* for (i = 0; i < 16;) */
288 /* this really should be a function, not a macro but i'm lazy */
289 .macro read_write_disk_sectors cmd
300 /* save nb_sectors */
329 movw $0, 0(%bx) /* read c,h,s */
334 mov 6(%bx), %ax /* total_sectors */
335 mov 2(%bp), %si /* *= heads */
337 add 4(%bp), %ax /* += sectors - 1 */
339 push 4(%bx) /* total_heads */
341 push 6(%bx) /* total_sectors */
346 push 0(%bp) /* cylinders */
361 movw \cmd, 0(%bx) /* read */
362 movw 6(%bp), %ax /* nb_sectors */
364 movw %es, 4(%bx) /* segment */
365 movw 8(%bp), %ax /* offset */
367 movw %dx, 8(%bx) /* sector */
393 read_write_disk_sectors $0x01
396 read_write_disk_sectors $0x02
398 read_disk_drive_parameters:
401 /* allocate memory for packet, pointer gets returned in bx */
405 movw $0, 0(%bx) /* cmd = 0, read c,h,s */
410 /* normalize sector value */
415 /* normalize cylinders */
418 /* normalize heads */
446 /* do this last since it's the most sensitive */
450 alternate_disk_reset:
455 read_disk_drive_size:
459 movw $0, 0(%bx) /* cmd = 0, read c,h,s */
464 /* cylinders - 1 to cx:dx */
494 check_if_extensions_present:
501 .macro extended_read_write_sectors cmd
512 movw \cmd, 0(%bp) /* read */
513 movw 2(%si), %ax /* nb_sectors */
515 movw 4(%si), %ax /* offset */
517 movw 6(%si), %ax /* segment */
519 movw 8(%si), %ax /* block */
541 extended_read_sectors:
542 extended_read_write_sectors $0x01
544 extended_write_sectors:
545 extended_read_write_sectors $0x02
547 get_extended_drive_parameters:
555 movw $0, 0(%bp) /* read c,h,s */
584 /* set total number of sectors */
594 /* number of bytes per sector */
608 terminate_disk_emulation:
617 /* write old handler as return address onto stack */
625 mov (OLD_INT13), %eax
639 call read_disk_sectors
644 call read_disk_drive_parameters
649 call read_disk_drive_size
654 call check_if_extensions_present
659 call extended_read_sectors
664 call get_extended_drive_parameters
669 call terminate_disk_emulation
674 call alternate_disk_reset
679 call write_disk_sectors
684 call extended_write_sectors
687 int $0x18 /* boot failed */