These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / seabios / src / fw / csm.c
1 // Compatibility Support Module (CSM) for UEFI / EDK-II
2 //
3 // Copyright © 2013 Intel Corporation
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "bregs.h" // struct bregs
8 #include "config.h" // CONFIG_*
9 #include "e820map.h" // e820_add
10 #include "farptr.h" // MAKE_FLATPTR
11 #include "hw/pci.h" // pci_probe_devices
12 #include "hw/pic.h" // pic_irqmask_read
13 #include "malloc.h" // malloc_csm_preinit
14 #include "memmap.h" // SYMBOL
15 #include "output.h" // dprintf
16 #include "paravirt.h" // qemu_preinit
17 #include "stacks.h" // wait_threads
18 #include "std/acpi.h" // RSDP_SIGNATURE
19 #include "std/bda.h" // struct bios_data_area_s
20 #include "std/optionrom.h" // struct rom_header
21 #include "util.h" // copy_smbios
22
23 #define UINT8 u8
24 #define UINT16 u16
25 #define UINT32 u32
26 #include "std/LegacyBios.h"
27
28 struct rsdp_descriptor csm_rsdp VARFSEG __aligned(16);
29
30 EFI_COMPATIBILITY16_TABLE csm_compat_table VARFSEG __aligned(16) = {
31     .Signature = 0x24454649,
32     .TableChecksum = 0 /* Filled in by checkrom.py */,
33     .TableLength = sizeof(csm_compat_table),
34     .Compatibility16CallSegment = SEG_BIOS,
35     .Compatibility16CallOffset = 0 /* Filled in by checkrom.py */,
36     .OemIdStringPointer = (u32)"SeaBIOS",
37     .AcpiRsdPtrPointer = (u32)&csm_rsdp,
38 };
39
40 EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
41 EFI_TO_COMPATIBILITY16_BOOT_TABLE *csm_boot_table;
42
43 static u16 PICMask = PIC_IRQMASK_DEFAULT;
44
45 extern void __csm_return(struct bregs *regs) __noreturn;
46
47 static void
48 csm_return(struct bregs *regs)
49 {
50     u32 rommax = rom_get_max();
51
52     dprintf(3, "handle_csm returning AX=%04x\n", regs->ax);
53
54     csm_compat_table.UmaAddress = rommax;
55     csm_compat_table.UmaSize = SYMBOL(final_readonly_start) - rommax;
56
57     PICMask = pic_irqmask_read();
58     __csm_return(regs);
59 }
60
61 static void
62 csm_maininit(struct bregs *regs)
63 {
64     interface_init();
65     pci_probe_devices();
66
67     csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
68     csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
69
70     regs->ax = 0;
71
72     csm_return(regs);
73 }
74
75 /* Legacy16InitializeYourself */
76 static void
77 handle_csm_0000(struct bregs *regs)
78 {
79     qemu_preinit();
80
81     dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es,
82             regs->bx);
83
84     csm_init_table = MAKE_FLATPTR(regs->es, regs->bx);
85
86     dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB);
87     dprintf(3, "HiPmmMemory     %08x\n", csm_init_table->HiPmmMemory);
88     dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes);
89     dprintf(3, "ReverseThunk    %04x:%04x\n", csm_init_table->ReverseThunkCallSegment,
90             csm_init_table->ReverseThunkCallOffset);
91     dprintf(3, "NumE820Entries  %08x\n", csm_init_table->NumberE820Entries);
92     dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb);
93     dprintf(3, "ThunkStart      %08x\n", csm_init_table->ThunkStart);
94     dprintf(3, "ThunkSize       %08x\n", csm_init_table->ThunkSizeInBytes);
95     dprintf(3, "LoPmmMemory     %08x\n", csm_init_table->LowPmmMemory);
96     dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes);
97
98     malloc_csm_preinit(csm_init_table->LowPmmMemory,
99                        csm_init_table->LowPmmMemorySizeInBytes,
100                        csm_init_table->HiPmmMemory,
101                        csm_init_table->HiPmmMemorySizeInBytes);
102     reloc_preinit(csm_maininit, regs);
103 }
104
105 /* Legacy16UpdateBbs */
106 static void
107 handle_csm_0001(struct bregs *regs)
108 {
109     if (!CONFIG_BOOT) {
110         regs->ax = 1;
111         return;
112     }
113
114     dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx);
115
116     csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx);
117     dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion);
118     dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion);
119     dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable);
120     dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable);
121     dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength);
122 //    dprintf(3, "SioData %08x\n", csm_boot_table->SioData);
123     dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType);
124     dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask);
125     dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries);
126 //    dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo);
127     dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries);
128     dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable);
129     dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable);
130     dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb);
131     dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable);
132
133     regs->ax = 0;
134 }
135
136 /* PrepareToBoot */
137 static void
138 handle_csm_0002(struct bregs *regs)
139 {
140     if (!CONFIG_BOOT) {
141         regs->ax = 1;
142         return;
143     }
144
145     dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx);
146
147     struct e820entry *p = (void *)csm_compat_table.E820Pointer;
148     int i;
149     for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++)
150         e820_add(p[i].start, p[i].size, p[i].type);
151
152     if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) {
153         u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes;
154         e820_add(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED);
155     }
156
157     // For PCIBIOS 1ab10e
158     if (csm_compat_table.IrqRoutingTablePointer &&
159         csm_compat_table.IrqRoutingTableLength) {
160         PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer;
161         dprintf(3, "CSM PIRQ table at %p\n", PirAddr);
162     }
163
164     // For find_resume_vector()... and find_acpi_features()
165     if (csm_rsdp.signature == RSDP_SIGNATURE) {
166         RsdpAddr = &csm_rsdp;
167         dprintf(3, "CSM ACPI RSDP at %p\n", RsdpAddr);
168
169         find_acpi_features();
170     }
171
172     // SMBIOS table needs to be copied into the f-seg
173     // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it
174     if (csm_boot_table->SmbiosTable && !SMBiosAddr)
175         copy_smbios((void *)csm_boot_table->SmbiosTable);
176
177     // MPTABLE is just there; we don't care where.
178
179     // EFI may have reinitialised the video using its *own* driver.
180     enable_vga_console();
181
182     // EFI fills this in for us. Zero it for now...
183     struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
184     bda->hdcount = 0;
185
186     thread_setup();
187     mathcp_setup();
188     timer_setup();
189     clock_setup();
190     device_hardware_setup();
191     wait_threads();
192     interactive_bootmenu();
193
194     prepareboot();
195
196     regs->ax = 0;
197 }
198
199 /* Boot */
200 static void
201 handle_csm_0003(struct bregs *regs)
202 {
203     if (!CONFIG_BOOT) {
204         regs->ax = 1;
205         return;
206     }
207
208     dprintf(3, "Boot\n");
209
210     startBoot();
211
212     regs->ax = 1;
213 }
214
215 /* Legacy16DispatchOprom */
216 static void
217 handle_csm_0005(struct bregs *regs)
218 {
219     EFI_DISPATCH_OPROM_TABLE *table = MAKE_FLATPTR(regs->es, regs->bx);
220     struct rom_header *rom;
221     u16 bdf;
222
223     if (!CONFIG_OPTIONROMS) {
224         regs->ax = 1;
225         return;
226     }
227
228     dprintf(3, "Legacy16DispatchOprom rom %p\n", table);
229
230     dprintf(3, "OpromSegment   %04x\n", table->OpromSegment);
231     dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
232     dprintf(3, "PnPInstallationCheck %04x:%04x\n",
233             table->PnPInstallationCheckSegment,
234             table->PnPInstallationCheckOffset);
235     dprintf(3, "RuntimeSegment %04x\n", table->RuntimeSegment);
236
237     rom = MAKE_FLATPTR(table->OpromSegment, 0);
238     bdf = pci_bus_devfn_to_bdf(table->PciBus, table->PciDeviceFunction);
239
240     rom_reserve(rom->size * 512);
241
242     // XX PnP seg/ofs should never be other than default
243     callrom(rom, bdf);
244
245     rom_confirm(rom->size * 512);
246
247     regs->bx = 0; // FIXME
248     regs->ax = 0;
249 }
250
251 /* Legacy16GetTableAddress */
252 static void
253 handle_csm_0006(struct bregs *regs)
254 {
255     u16 size = regs->cx;
256     u16 align = regs->dx;
257     u16 region = regs->bx; // (1 for F000 seg, 2 for E000 seg, 0 for either)
258     void *chunk = NULL;
259
260     if (!region)
261         region = 3;
262
263     dprintf(3, "Legacy16GetTableAddress size %x align %x region %d\n",
264         size, align, region);
265
266     if (region & 2)
267         chunk = _malloc(&ZoneLow, size, align);
268     if (!chunk && (region & 1))
269         chunk = _malloc(&ZoneFSeg, size, align);
270
271     dprintf(3, "Legacy16GetTableAddress size %x align %x region %d yields %p\n",
272         size, align, region, chunk);
273     if (chunk) {
274         regs->ds = FLATPTR_TO_SEG(chunk);
275         regs->bx = FLATPTR_TO_OFFSET(chunk);
276         regs->ax = 0;
277     } else {
278         regs->ax = 1;
279     }
280 }
281
282 void VISIBLE32INIT
283 handle_csm(struct bregs *regs)
284 {
285     ASSERT32FLAT();
286
287     if (!CONFIG_CSM)
288         return;
289
290     dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax);
291
292     pic_irqmask_write(PICMask);
293
294     switch(regs->ax) {
295     case 0000: handle_csm_0000(regs); break;
296     case 0001: handle_csm_0001(regs); break;
297     case 0002: handle_csm_0002(regs); break;
298     case 0003: handle_csm_0003(regs); break;
299 //    case 0004: handle_csm_0004(regs); break;
300     case 0005: handle_csm_0005(regs); break;
301     case 0006: handle_csm_0006(regs); break;
302 //    case 0007: handle_csm_0007(regs); break;
303 //    case 0008: hamdle_csm_0008(regs); break;
304     default: regs->al = 1;
305     }
306
307     csm_return(regs);
308 }
309
310 int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave)
311 {
312     if (!csm_boot_table)
313         return -1;
314     BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
315     int index = 1 + (chanid * 2) + slave;
316     dprintf(3, "CSM bootprio for ATA%d,%d (index %d) is %d\n", chanid, slave,
317             index, bbs[index].BootPriority);
318     return bbs[index].BootPriority;
319 }
320
321 int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid)
322 {
323     if (!csm_boot_table)
324         return -1;
325     BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
326     dprintf(3, "CSM bootprio for FDC is %d\n", bbs[0].BootPriority);
327     return bbs[0].BootPriority;
328 }
329
330 int csm_bootprio_pci(struct pci_device *pci)
331 {
332     if (!csm_boot_table)
333         return -1;
334     BBS_TABLE *bbs = (void *)csm_boot_table->BbsTable;
335     int i;
336
337     for (i = 5; i < csm_boot_table->NumberBbsEntries; i++) {
338         if (pci->bdf == pci_to_bdf(bbs[i].Bus, bbs[i].Device, bbs[i].Function)) {
339             dprintf(3, "CSM bootprio for PCI(%d,%d,%d) is %d\n", bbs[i].Bus,
340                     bbs[i].Device, bbs[i].Function, bbs[i].BootPriority);
341             return bbs[i].BootPriority;
342         }
343     }
344     return -1;
345 }