blob: 2a270864bc0016b057a15338727a389bd3e7d464 [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'Connora2e73802008-02-27 10:27:00 -050031
32 // XXX - latest cvs has BEV description
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050033}
34
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050035//--------------------------------------------------------------------------
36// print_boot_failure
37// displays the reason why boot failed
38//--------------------------------------------------------------------------
39static void
40print_boot_failure(u16 type, u8 reason)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050041{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050042 if (type == 0 || type > 0x3)
43 BX_PANIC("Bad drive type\n");
44
Kevin O'Connora2e73802008-02-27 10:27:00 -050045 printf("Boot failed");
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050046 if (type < 4) {
47 /* Report the reason too */
48 if (reason==0)
49 printf(": not a bootable disk");
50 else
51 printf(": could not read the boot disk");
52 }
Kevin O'Connora2e73802008-02-27 10:27:00 -050053 printf("\n\n");
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050054}
55
56static void
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050057try_boot(u16 seq_nr)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050058{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050059 SET_IPL(sequence, seq_nr);
60 u16 bootseg;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050061 u8 bootdrv = 0;
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050062 u16 bootdev, bootip;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050063
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050064 if (CONFIG_ELTORITO_BOOT) {
65 bootdev = inb_cmos(CMOS_BIOS_BOOTFLAG2);
66 bootdev |= ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4);
67 bootdev >>= 4 * seq_nr;
68 bootdev &= 0xf;
69 if (bootdev == 0)
70 BX_PANIC("No bootable device.\n");
71
72 /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
73 bootdev -= 1;
74 } else {
75 if (seq_nr ==2)
76 BX_PANIC("No more boot devices.");
77 if (!!(inb_cmos(CMOS_BIOS_CONFIG) & 0x20) ^ (seq_nr == 1))
78 /* Boot from floppy if the bit is set or it's the second boot */
79 bootdev = 0x00;
80 else
81 bootdev = 0x01;
82 }
83
84 if (bootdev >= GET_IPL(count)) {
85 BX_INFO("Invalid boot device (0x%x)\n", bootdev);
86 return;
87 }
88 u16 type = GET_IPL(table[bootdev].type);
89
90 /* Do the loading, and set up vector as a far pointer to the boot
91 * address, and bootdrv as the boot drive */
92 print_boot_device(type);
93
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050094 struct bregs cr;
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050095 switch(type) {
96 case IPL_TYPE_FLOPPY: /* FDD */
97 case IPL_TYPE_HARDDISK: /* HDD */
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050098
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050099 bootdrv = (type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
100 bootseg = 0x07c0;
101
102 // Read sector
103 memset(&cr, 0, sizeof(cr));
104 cr.dl = bootdrv;
105 cr.es = bootseg;
106 cr.ah = 2;
107 cr.al = 1;
108 cr.cl = 1;
109 call16_int(0x13, &cr);
110
111 if (cr.flags & F_CF) {
112 print_boot_failure(type, 1);
113 return;
114 }
115
116 /* Always check the signature on a HDD boot sector; on FDD,
117 * only do the check if the CMOS doesn't tell us to skip it */
118 if ((type != IPL_TYPE_FLOPPY)
119 || !((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0x01))) {
120 if (GET_FARVAR(bootseg, *(u16*)0x1fe) != 0xaa55) {
121 print_boot_failure(type, 0);
122 return;
123 }
124 }
125
126 /* Canonicalize bootseg:bootip */
127 bootip = (bootseg & 0x0fff) << 4;
128 bootseg &= 0xf000;
129 break;
130 case IPL_TYPE_CDROM: /* CD-ROM */
131 // XXX
132 return;
133 break;
134 case IPL_TYPE_BEV: {
135 /* Expansion ROM with a Bootstrap Entry Vector (a far
136 * pointer) */
137 u32 vector = GET_IPL(table[bootdev].vector);
138 bootseg = vector >> 16;
139 bootip = vector & 0xffff;
140 break;
141 }
142 default:
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500143 return;
144 }
145
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500146 memset(&cr, 0, sizeof(cr));
147 cr.ip = bootip;
148 cr.cs = bootseg;
149 // Set the magic number in ax and the boot drive in dl.
150 cr.dl = bootdrv;
151 cr.ax = 0xaa55;
152 call16(&cr);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500153
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500154 // Boot failed: invoke the boot recovery function
155 memset(&cr, 0, sizeof(cr));
156 call16_int(0x18, &cr);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500157}
158
159// Boot Failure recovery: try the next device.
160void VISIBLE
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500161handle_18()
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500162{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500163 debug_enter(NULL);
164 u16 seq = GET_IPL(sequence) + 1;
165 try_boot(seq);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500166}
167
168// INT 19h Boot Load Service Entry Point
169void VISIBLE
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500170handle_19()
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500171{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500172 debug_enter(NULL);
173 try_boot(0);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500174}
175
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500176// Called from 32bit code - start boot process
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500177void VISIBLE
178begin_boot()
179{
180 irq_enable();
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500181 struct bregs br;
182 memset(&br, 0, sizeof(br));
183 call16_int(0x19, &br);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500184}