blob: af22e1eb83ed7781ffa0552f13125817c684b9d4 [file] [log] [blame]
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05001// 16bit code to load disk image and start system boot.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2002 MandrakeSoft S.A.
5//
6// This file may be distributed under the terms of the GNU GPLv3 license.
7
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05008#include "util.h" // irq_enable
9#include "biosvar.h" // struct bregs
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050010#include "config.h" // CONFIG_*
11#include "cmos.h" // inb_cmos
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050012
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050013//--------------------------------------------------------------------------
14// print_boot_device
15// displays the boot device
16//--------------------------------------------------------------------------
17
18static const char drivetypes[][10]={
19 "", "Floppy","Hard Disk","CD-Rom", "Network"
20};
21
22static void
23print_boot_device(u16 type)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050024{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050025 /* NIC appears as type 0x80 */
26 if (type == IPL_TYPE_BEV)
27 type = 0x4;
28 if (type == 0 || type > 0x4)
29 BX_PANIC("Bad drive type\n");
30 printf("Booting from %s...\n", drivetypes[type]);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050031}
32
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050033//--------------------------------------------------------------------------
34// print_boot_failure
35// displays the reason why boot failed
36//--------------------------------------------------------------------------
37static void
38print_boot_failure(u16 type, u8 reason)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050039{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050040 if (type == 0 || type > 0x3)
41 BX_PANIC("Bad drive type\n");
42
43 printf("Boot from %s failed", drivetypes[type]);
44 if (type < 4) {
45 /* Report the reason too */
46 if (reason==0)
47 printf(": not a bootable disk");
48 else
49 printf(": could not read the boot disk");
50 }
51 printf("\n");
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050052}
53
54static void
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050055try_boot(u16 seq_nr)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050056{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050057 SET_IPL(sequence, seq_nr);
58 u16 bootseg;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050059 u8 bootdrv = 0;
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050060 u16 bootdev, bootip;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050061
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050062 if (CONFIG_ELTORITO_BOOT) {
63 bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2);
64 bootdev |= ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4);
65 bootdev >>= 4 * seq_nr;
66 bootdev &= 0xf;
67 if (bootdev == 0)
68 BX_PANIC("No bootable device.\n");
69
70 /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
71 bootdev -= 1;
72 } else {
73 if (seq_nr ==2)
74 BX_PANIC("No more boot devices.");
75 if (!!(inb_cmos(CMOS_BIOS_CONFIG) & 0x20) ^ (seq_nr == 1))
76 /* Boot from floppy if the bit is set or it's the second boot */
77 bootdev = 0x00;
78 else
79 bootdev = 0x01;
80 }
81
82 if (bootdev >= GET_IPL(count)) {
83 BX_INFO("Invalid boot device (0x%x)\n", bootdev);
84 return;
85 }
86 u16 type = GET_IPL(table[bootdev].type);
87
88 /* Do the loading, and set up vector as a far pointer to the boot
89 * address, and bootdrv as the boot drive */
90 print_boot_device(type);
91
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050092 struct bregs cr;
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050093 switch(type) {
94 case IPL_TYPE_FLOPPY: /* FDD */
95 case IPL_TYPE_HARDDISK: /* HDD */
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050096
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050097 bootdrv = (type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
98 bootseg = 0x07c0;
99
100 // Read sector
101 memset(&cr, 0, sizeof(cr));
102 cr.dl = bootdrv;
103 cr.es = bootseg;
104 cr.ah = 2;
105 cr.al = 1;
106 cr.cl = 1;
107 call16_int(0x13, &cr);
108
109 if (cr.flags & F_CF) {
110 print_boot_failure(type, 1);
111 return;
112 }
113
114 /* Always check the signature on a HDD boot sector; on FDD,
115 * only do the check if the CMOS doesn't tell us to skip it */
116 if ((type != IPL_TYPE_FLOPPY)
117 || !((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0x01))) {
118 if (GET_FARVAR(bootseg, *(u16*)0x1fe) != 0xaa55) {
119 print_boot_failure(type, 0);
120 return;
121 }
122 }
123
124 /* Canonicalize bootseg:bootip */
125 bootip = (bootseg & 0x0fff) << 4;
126 bootseg &= 0xf000;
127 break;
128 case IPL_TYPE_CDROM: /* CD-ROM */
129 // XXX
130 return;
131 break;
132 case IPL_TYPE_BEV: {
133 /* Expansion ROM with a Bootstrap Entry Vector (a far
134 * pointer) */
135 u32 vector = GET_IPL(table[bootdev].vector);
136 bootseg = vector >> 16;
137 bootip = vector & 0xffff;
138 break;
139 }
140 default:
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500141 return;
142 }
143
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500144 memset(&cr, 0, sizeof(cr));
145 cr.ip = bootip;
146 cr.cs = bootseg;
147 // Set the magic number in ax and the boot drive in dl.
148 cr.dl = bootdrv;
149 cr.ax = 0xaa55;
150 call16(&cr);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500151
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500152 // Boot failed: invoke the boot recovery function
153 memset(&cr, 0, sizeof(cr));
154 call16_int(0x18, &cr);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500155}
156
157// Boot Failure recovery: try the next device.
158void VISIBLE
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500159handle_18()
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500160{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500161 debug_enter(NULL);
162 u16 seq = GET_IPL(sequence) + 1;
163 try_boot(seq);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500164}
165
166// INT 19h Boot Load Service Entry Point
167void VISIBLE
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500168handle_19()
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500169{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500170 debug_enter(NULL);
171 try_boot(0);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500172}
173
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500174// Called from 32bit code - start boot process
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500175void VISIBLE
176begin_boot()
177{
178 irq_enable();
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500179 struct bregs br;
180 memset(&br, 0, sizeof(br));
181 call16_int(0x19, &br);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500182}