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 */