Separate out smp detection and mp table generation from rombios32.c
[seabios.git] / src / rombios32.c
1 /////////////////////////////////////////////////////////////////////////
2 //
3 //  32 bit Bochs BIOS init code
4 //  Copyright (C) 2006 Fabrice Bellard
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2 of the License, or (at your option) any later version.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
19
20 #include "util.h" // dprintf
21 #include "pci.h" // PCIDevice
22 #include "types.h" // u32
23 #include "config.h" // CONFIG_*
24 #include "memmap.h" // bios_table_cur_addr
25 #include "acpi.h" // acpi_bios_init
26
27 u32 cpuid_signature;
28 u32 cpuid_features;
29 u32 cpuid_ext_features;
30 u8 bios_uuid[16];
31
32 void uuid_probe(void)
33 {
34     // Default to UUID not set
35     memset(bios_uuid, 0, 16);
36
37     if (! CONFIG_QEMU)
38         return;
39
40     // check if backdoor port exists
41     u32 eax, ebx, ecx, edx;
42     asm volatile ("outl %%eax, %%dx"
43                   : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
44                   : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
45     if (ebx != 0x564d5868)
46         return;
47
48     u32 *uuid_ptr = (u32 *)bios_uuid;
49     // get uuid
50     asm volatile ("outl %%eax, %%dx"
51                   : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
52                   : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
53     uuid_ptr[0] = eax;
54     uuid_ptr[1] = ebx;
55     uuid_ptr[2] = ecx;
56     uuid_ptr[3] = edx;
57 }
58
59 void cpu_probe(void)
60 {
61     u32 eax, ebx, ecx, edx;
62     cpuid(1, &eax, &ebx, &ecx, &edx);
63     cpuid_signature = eax;
64     cpuid_features = edx;
65     cpuid_ext_features = ecx;
66 }
67
68 /****************************************************/
69 /* PCI init */
70
71 #define PCI_ADDRESS_SPACE_MEM           0x00
72 #define PCI_ADDRESS_SPACE_IO            0x01
73 #define PCI_ADDRESS_SPACE_MEM_PREFETCH  0x08
74
75 #define PCI_ROM_SLOT 6
76 #define PCI_NUM_REGIONS 7
77
78 #define PCI_DEVICES_MAX 64
79
80 static u32 pci_bios_io_addr;
81 static u32 pci_bios_mem_addr;
82 static u32 pci_bios_bigmem_addr;
83 /* host irqs corresponding to PCI irqs A-D */
84 static u8 pci_irqs[4] = { 11, 9, 11, 9 };
85
86 static void pci_set_io_region_addr(PCIDevice d, int region_num, u32 addr)
87 {
88     u16 cmd;
89     u32 ofs, old_addr;
90
91     if ( region_num == PCI_ROM_SLOT ) {
92         ofs = 0x30;
93     }else{
94         ofs = 0x10 + region_num * 4;
95     }
96
97     old_addr = pci_config_readl(d, ofs);
98
99     pci_config_writel(d, ofs, addr);
100     dprintf(1, "region %d: 0x%08x\n", region_num, addr);
101
102     /* enable memory mappings */
103     cmd = pci_config_readw(d, PCI_COMMAND);
104     if ( region_num == PCI_ROM_SLOT )
105         cmd |= 2;
106     else if (old_addr & PCI_ADDRESS_SPACE_IO)
107         cmd |= 1;
108     else
109         cmd |= 2;
110     pci_config_writew(d, PCI_COMMAND, cmd);
111 }
112
113 /* return the global irq number corresponding to a given device irq
114    pin. We could also use the bus number to have a more precise
115    mapping. */
116 static int pci_slot_get_pirq(PCIDevice pci_dev, int irq_num)
117 {
118     int slot_addend;
119     slot_addend = (pci_dev.devfn >> 3) - 1;
120     return (irq_num + slot_addend) & 3;
121 }
122
123 static void pci_bios_init_bridges(PCIDevice d)
124 {
125     u16 vendor_id, device_id;
126
127     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
128     device_id = pci_config_readw(d, PCI_DEVICE_ID);
129
130     if (vendor_id == 0x8086 && device_id == 0x7000) {
131         int i, irq;
132         u8 elcr[2];
133
134         /* PIIX3 bridge */
135
136         elcr[0] = 0x00;
137         elcr[1] = 0x00;
138         for(i = 0; i < 4; i++) {
139             irq = pci_irqs[i];
140             /* set to trigger level */
141             elcr[irq >> 3] |= (1 << (irq & 7));
142             /* activate irq remapping in PIIX */
143             pci_config_writeb(d, 0x60 + i, irq);
144         }
145         outb(elcr[0], 0x4d0);
146         outb(elcr[1], 0x4d1);
147         dprintf(1, "PIIX3 init: elcr=%02x %02x\n",
148                 elcr[0], elcr[1]);
149     }
150 }
151
152 static void pci_bios_init_device(PCIDevice d)
153 {
154     int class;
155     u32 *paddr;
156     int i, pin, pic_irq, vendor_id, device_id;
157
158     class = pci_config_readw(d, PCI_CLASS_DEVICE);
159     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
160     device_id = pci_config_readw(d, PCI_DEVICE_ID);
161     dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n",
162             d.bus, d.devfn, vendor_id, device_id);
163     switch(class) {
164     case 0x0101:
165         if (vendor_id == 0x8086 && device_id == 0x7010) {
166             /* PIIX3 IDE */
167             pci_config_writew(d, 0x40, 0x8000); // enable IDE0
168             pci_config_writew(d, 0x42, 0x8000); // enable IDE1
169             goto default_map;
170         } else {
171             /* IDE: we map it as in ISA mode */
172             pci_set_io_region_addr(d, 0, 0x1f0);
173             pci_set_io_region_addr(d, 1, 0x3f4);
174             pci_set_io_region_addr(d, 2, 0x170);
175             pci_set_io_region_addr(d, 3, 0x374);
176         }
177         break;
178     case 0x0300:
179         if (vendor_id != 0x1234)
180             goto default_map;
181         /* VGA: map frame buffer to default Bochs VBE address */
182         pci_set_io_region_addr(d, 0, 0xE0000000);
183         break;
184     case 0x0800:
185         /* PIC */
186         if (vendor_id == 0x1014) {
187             /* IBM */
188             if (device_id == 0x0046 || device_id == 0xFFFF) {
189                 /* MPIC & MPIC2 */
190                 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
191             }
192         }
193         break;
194     case 0xff00:
195         if (vendor_id == 0x0106b &&
196             (device_id == 0x0017 || device_id == 0x0022)) {
197             /* macio bridge */
198             pci_set_io_region_addr(d, 0, 0x80800000);
199         }
200         break;
201     default:
202     default_map:
203         /* default memory mappings */
204         for(i = 0; i < PCI_NUM_REGIONS; i++) {
205             int ofs;
206             u32 val, size ;
207
208             if (i == PCI_ROM_SLOT)
209                 ofs = 0x30;
210             else
211                 ofs = 0x10 + i * 4;
212             pci_config_writel(d, ofs, 0xffffffff);
213             val = pci_config_readl(d, ofs);
214             if (val != 0) {
215                 size = (~(val & ~0xf)) + 1;
216                 if (val & PCI_ADDRESS_SPACE_IO)
217                     paddr = &pci_bios_io_addr;
218                 else if (size >= 0x04000000)
219                     paddr = &pci_bios_bigmem_addr;
220                 else
221                     paddr = &pci_bios_mem_addr;
222                 *paddr = (*paddr + size - 1) & ~(size - 1);
223                 pci_set_io_region_addr(d, i, *paddr);
224                 *paddr += size;
225             }
226         }
227         break;
228     }
229
230     /* map the interrupt */
231     pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
232     if (pin != 0) {
233         pin = pci_slot_get_pirq(d, pin - 1);
234         pic_irq = pci_irqs[pin];
235         pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
236     }
237
238     if (vendor_id == 0x8086 && device_id == 0x7113) {
239         /* PIIX4 Power Management device (for ACPI) */
240         u32 pm_io_base = BUILD_PM_IO_BASE;
241         pci_config_writel(d, 0x40, pm_io_base | 1);
242         pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */
243         u32 smb_io_base = BUILD_SMB_IO_BASE;
244         pci_config_writel(d, 0x90, smb_io_base | 1);
245         pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */
246     }
247 }
248
249 void pci_for_each_device(void (*init_func)(PCIDevice d))
250 {
251     int bus, devfn;
252     u16 vendor_id, device_id;
253
254     for(bus = 0; bus < 1; bus++) {
255         for(devfn = 0; devfn < 256; devfn++) {
256             PCIDevice d = pci_bd(bus, devfn);
257             vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
258             device_id = pci_config_readw(d, PCI_DEVICE_ID);
259             if (vendor_id != 0xffff || device_id != 0xffff) {
260                 init_func(d);
261             }
262         }
263     }
264 }
265
266 void pci_bios_init(void)
267 {
268     pci_bios_io_addr = 0xc000;
269     pci_bios_mem_addr = 0xf0000000;
270     pci_bios_bigmem_addr = GET_EBDA(ram_size);
271     if (pci_bios_bigmem_addr < 0x90000000)
272         pci_bios_bigmem_addr = 0x90000000;
273
274     pci_for_each_device(pci_bios_init_bridges);
275
276     pci_for_each_device(pci_bios_init_device);
277 }
278
279 /* SMBIOS entry point -- must be written to a 16-bit aligned address
280    between 0xf0000 and 0xfffff.
281  */
282 struct smbios_entry_point {
283         char anchor_string[4];
284         u8 checksum;
285         u8 length;
286         u8 smbios_major_version;
287         u8 smbios_minor_version;
288         u16 max_structure_size;
289         u8 entry_point_revision;
290         u8 formatted_area[5];
291         char intermediate_anchor_string[5];
292         u8 intermediate_checksum;
293         u16 structure_table_length;
294         u32 structure_table_address;
295         u16 number_of_structures;
296         u8 smbios_bcd_revision;
297 } __attribute__((__packed__));
298
299 /* This goes at the beginning of every SMBIOS structure. */
300 struct smbios_structure_header {
301         u8 type;
302         u8 length;
303         u16 handle;
304 } __attribute__((__packed__));
305
306 /* SMBIOS type 0 - BIOS Information */
307 struct smbios_type_0 {
308         struct smbios_structure_header header;
309         u8 vendor_str;
310         u8 bios_version_str;
311         u16 bios_starting_address_segment;
312         u8 bios_release_date_str;
313         u8 bios_rom_size;
314         u8 bios_characteristics[8];
315         u8 bios_characteristics_extension_bytes[2];
316         u8 system_bios_major_release;
317         u8 system_bios_minor_release;
318         u8 embedded_controller_major_release;
319         u8 embedded_controller_minor_release;
320 } __attribute__((__packed__));
321
322 /* SMBIOS type 1 - System Information */
323 struct smbios_type_1 {
324         struct smbios_structure_header header;
325         u8 manufacturer_str;
326         u8 product_name_str;
327         u8 version_str;
328         u8 serial_number_str;
329         u8 uuid[16];
330         u8 wake_up_type;
331         u8 sku_number_str;
332         u8 family_str;
333 } __attribute__((__packed__));
334
335 /* SMBIOS type 3 - System Enclosure (v2.3) */
336 struct smbios_type_3 {
337         struct smbios_structure_header header;
338         u8 manufacturer_str;
339         u8 type;
340         u8 version_str;
341         u8 serial_number_str;
342         u8 asset_tag_number_str;
343         u8 boot_up_state;
344         u8 power_supply_state;
345         u8 thermal_state;
346         u8 security_status;
347     u32 oem_defined;
348     u8 height;
349     u8 number_of_power_cords;
350     u8 contained_element_count;
351     // contained elements follow
352 } __attribute__((__packed__));
353
354 /* SMBIOS type 4 - Processor Information (v2.0) */
355 struct smbios_type_4 {
356         struct smbios_structure_header header;
357         u8 socket_designation_str;
358         u8 processor_type;
359         u8 processor_family;
360         u8 processor_manufacturer_str;
361         u32 processor_id[2];
362         u8 processor_version_str;
363         u8 voltage;
364         u16 external_clock;
365         u16 max_speed;
366         u16 current_speed;
367         u8 status;
368         u8 processor_upgrade;
369 } __attribute__((__packed__));
370
371 /* SMBIOS type 16 - Physical Memory Array
372  *   Associated with one type 17 (Memory Device).
373  */
374 struct smbios_type_16 {
375         struct smbios_structure_header header;
376         u8 location;
377         u8 use;
378         u8 error_correction;
379         u32 maximum_capacity;
380         u16 memory_error_information_handle;
381         u16 number_of_memory_devices;
382 } __attribute__((__packed__));
383
384 /* SMBIOS type 17 - Memory Device
385  *   Associated with one type 19
386  */
387 struct smbios_type_17 {
388         struct smbios_structure_header header;
389         u16 physical_memory_array_handle;
390         u16 memory_error_information_handle;
391         u16 total_width;
392         u16 data_width;
393         u16 size;
394         u8 form_factor;
395         u8 device_set;
396         u8 device_locator_str;
397         u8 bank_locator_str;
398         u8 memory_type;
399         u16 type_detail;
400 } __attribute__((__packed__));
401
402 /* SMBIOS type 19 - Memory Array Mapped Address */
403 struct smbios_type_19 {
404         struct smbios_structure_header header;
405         u32 starting_address;
406         u32 ending_address;
407         u16 memory_array_handle;
408         u8 partition_width;
409 } __attribute__((__packed__));
410
411 /* SMBIOS type 20 - Memory Device Mapped Address */
412 struct smbios_type_20 {
413         struct smbios_structure_header header;
414         u32 starting_address;
415         u32 ending_address;
416         u16 memory_device_handle;
417         u16 memory_array_mapped_address_handle;
418         u8 partition_row_position;
419         u8 interleave_position;
420         u8 interleaved_data_depth;
421 } __attribute__((__packed__));
422
423 /* SMBIOS type 32 - System Boot Information */
424 struct smbios_type_32 {
425         struct smbios_structure_header header;
426         u8 reserved[6];
427         u8 boot_status;
428 } __attribute__((__packed__));
429
430 /* SMBIOS type 127 -- End-of-table */
431 struct smbios_type_127 {
432         struct smbios_structure_header header;
433 } __attribute__((__packed__));
434
435 static void
436 smbios_entry_point_init(void *start,
437                         u16 max_structure_size,
438                         u16 structure_table_length,
439                         u32 structure_table_address,
440                         u16 number_of_structures)
441 {
442     struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
443
444     memcpy(ep->anchor_string, "_SM_", 4);
445     ep->length = 0x1f;
446     ep->smbios_major_version = 2;
447     ep->smbios_minor_version = 4;
448     ep->max_structure_size = max_structure_size;
449     ep->entry_point_revision = 0;
450     memset(ep->formatted_area, 0, 5);
451     memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
452
453     ep->structure_table_length = structure_table_length;
454     ep->structure_table_address = structure_table_address;
455     ep->number_of_structures = number_of_structures;
456     ep->smbios_bcd_revision = 0x24;
457
458     ep->checksum = 0;
459     ep->intermediate_checksum = 0;
460
461     ep->checksum = -checksum(start, 0x10);
462
463     ep->intermediate_checksum = -checksum(start + 0x10, ep->length - 0x10);
464 }
465
466 /* Type 0 -- BIOS Information */
467 #define RELEASE_DATE_STR "01/01/2007"
468 static void *
469 smbios_type_0_init(void *start)
470 {
471     struct smbios_type_0 *p = (struct smbios_type_0 *)start;
472
473     p->header.type = 0;
474     p->header.length = sizeof(struct smbios_type_0);
475     p->header.handle = 0;
476
477     p->vendor_str = 1;
478     p->bios_version_str = 1;
479     p->bios_starting_address_segment = 0xe800;
480     p->bios_release_date_str = 2;
481     p->bios_rom_size = 0; /* FIXME */
482
483     memset(p->bios_characteristics, 0, 7);
484     p->bios_characteristics[7] = 0x08; /* BIOS characteristics not supported */
485     p->bios_characteristics_extension_bytes[0] = 0;
486     p->bios_characteristics_extension_bytes[1] = 0;
487
488     p->system_bios_major_release = 1;
489     p->system_bios_minor_release = 0;
490     p->embedded_controller_major_release = 0xff;
491     p->embedded_controller_minor_release = 0xff;
492
493     start += sizeof(struct smbios_type_0);
494     memcpy((char *)start, CONFIG_APPNAME, sizeof(CONFIG_APPNAME));
495     start += sizeof(CONFIG_APPNAME);
496     memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR));
497     start += sizeof(RELEASE_DATE_STR);
498     *((u8 *)start) = 0;
499
500     return start+1;
501 }
502
503 /* Type 1 -- System Information */
504 static void *
505 smbios_type_1_init(void *start)
506 {
507     struct smbios_type_1 *p = (struct smbios_type_1 *)start;
508     p->header.type = 1;
509     p->header.length = sizeof(struct smbios_type_1);
510     p->header.handle = 0x100;
511
512     p->manufacturer_str = 0;
513     p->product_name_str = 0;
514     p->version_str = 0;
515     p->serial_number_str = 0;
516
517     memcpy(p->uuid, bios_uuid, 16);
518
519     p->wake_up_type = 0x06; /* power switch */
520     p->sku_number_str = 0;
521     p->family_str = 0;
522
523     start += sizeof(struct smbios_type_1);
524     *((u16 *)start) = 0;
525
526     return start+2;
527 }
528
529 /* Type 3 -- System Enclosure */
530 static void *
531 smbios_type_3_init(void *start)
532 {
533     struct smbios_type_3 *p = (struct smbios_type_3 *)start;
534
535     p->header.type = 3;
536     p->header.length = sizeof(struct smbios_type_3);
537     p->header.handle = 0x300;
538
539     p->manufacturer_str = 0;
540     p->type = 0x01; /* other */
541     p->version_str = 0;
542     p->serial_number_str = 0;
543     p->asset_tag_number_str = 0;
544     p->boot_up_state = 0x03; /* safe */
545     p->power_supply_state = 0x03; /* safe */
546     p->thermal_state = 0x03; /* safe */
547     p->security_status = 0x02; /* unknown */
548     p->oem_defined = 0;
549     p->height = 0;
550     p->number_of_power_cords = 0;
551     p->contained_element_count = 0;
552
553     start += sizeof(struct smbios_type_3);
554     *((u16 *)start) = 0;
555
556     return start+2;
557 }
558
559 /* Type 4 -- Processor Information */
560 static void *
561 smbios_type_4_init(void *start, unsigned int cpu_number)
562 {
563     struct smbios_type_4 *p = (struct smbios_type_4 *)start;
564
565     p->header.type = 4;
566     p->header.length = sizeof(struct smbios_type_4);
567     p->header.handle = 0x400 + cpu_number;
568
569     p->socket_designation_str = 1;
570     p->processor_type = 0x03; /* CPU */
571     p->processor_family = 0x01; /* other */
572     p->processor_manufacturer_str = 0;
573
574     p->processor_id[0] = cpuid_signature;
575     p->processor_id[1] = cpuid_features;
576
577     p->processor_version_str = 0;
578     p->voltage = 0;
579     p->external_clock = 0;
580
581     p->max_speed = 0; /* unknown */
582     p->current_speed = 0; /* unknown */
583
584     p->status = 0x41; /* socket populated, CPU enabled */
585     p->processor_upgrade = 0x01; /* other */
586
587     start += sizeof(struct smbios_type_4);
588
589     memcpy((char *)start, "CPU  " "\0" "" "\0" "", 7);
590         ((char *)start)[4] = cpu_number + '0';
591
592     return start+7;
593 }
594
595 /* Type 16 -- Physical Memory Array */
596 static void *
597 smbios_type_16_init(void *start, u32 memsize)
598 {
599     struct smbios_type_16 *p = (struct smbios_type_16*)start;
600
601     p->header.type = 16;
602     p->header.length = sizeof(struct smbios_type_16);
603     p->header.handle = 0x1000;
604
605     p->location = 0x01; /* other */
606     p->use = 0x03; /* system memory */
607     p->error_correction = 0x01; /* other */
608     p->maximum_capacity = memsize * 1024;
609     p->memory_error_information_handle = 0xfffe; /* none provided */
610     p->number_of_memory_devices = 1;
611
612     start += sizeof(struct smbios_type_16);
613     *((u16 *)start) = 0;
614
615     return start + 2;
616 }
617
618 /* Type 17 -- Memory Device */
619 static void *
620 smbios_type_17_init(void *start, u32 memory_size_mb)
621 {
622     struct smbios_type_17 *p = (struct smbios_type_17 *)start;
623
624     p->header.type = 17;
625     p->header.length = sizeof(struct smbios_type_17);
626     p->header.handle = 0x1100;
627
628     p->physical_memory_array_handle = 0x1000;
629     p->total_width = 64;
630     p->data_width = 64;
631     /* truncate memory_size_mb to 16 bits and clear most significant
632        bit [indicates size in MB] */
633     p->size = (u16) memory_size_mb & 0x7fff;
634     p->form_factor = 0x09; /* DIMM */
635     p->device_set = 0;
636     p->device_locator_str = 1;
637     p->bank_locator_str = 0;
638     p->memory_type = 0x07; /* RAM */
639     p->type_detail = 0;
640
641     start += sizeof(struct smbios_type_17);
642     memcpy((char *)start, "DIMM 1", 7);
643     start += 7;
644     *((u8 *)start) = 0;
645
646     return start+1;
647 }
648
649 /* Type 19 -- Memory Array Mapped Address */
650 static void *
651 smbios_type_19_init(void *start, u32 memory_size_mb)
652 {
653     struct smbios_type_19 *p = (struct smbios_type_19 *)start;
654
655     p->header.type = 19;
656     p->header.length = sizeof(struct smbios_type_19);
657     p->header.handle = 0x1300;
658
659     p->starting_address = 0;
660     p->ending_address = (memory_size_mb-1) * 1024;
661     p->memory_array_handle = 0x1000;
662     p->partition_width = 1;
663
664     start += sizeof(struct smbios_type_19);
665     *((u16 *)start) = 0;
666
667     return start + 2;
668 }
669
670 /* Type 20 -- Memory Device Mapped Address */
671 static void *
672 smbios_type_20_init(void *start, u32 memory_size_mb)
673 {
674     struct smbios_type_20 *p = (struct smbios_type_20 *)start;
675
676     p->header.type = 20;
677     p->header.length = sizeof(struct smbios_type_20);
678     p->header.handle = 0x1400;
679
680     p->starting_address = 0;
681     p->ending_address = (memory_size_mb-1)*1024;
682     p->memory_device_handle = 0x1100;
683     p->memory_array_mapped_address_handle = 0x1300;
684     p->partition_row_position = 1;
685     p->interleave_position = 0;
686     p->interleaved_data_depth = 0;
687
688     start += sizeof(struct smbios_type_20);
689
690     *((u16 *)start) = 0;
691     return start+2;
692 }
693
694 /* Type 32 -- System Boot Information */
695 static void *
696 smbios_type_32_init(void *start)
697 {
698     struct smbios_type_32 *p = (struct smbios_type_32 *)start;
699
700     p->header.type = 32;
701     p->header.length = sizeof(struct smbios_type_32);
702     p->header.handle = 0x2000;
703     memset(p->reserved, 0, 6);
704     p->boot_status = 0; /* no errors detected */
705
706     start += sizeof(struct smbios_type_32);
707     *((u16 *)start) = 0;
708
709     return start+2;
710 }
711
712 /* Type 127 -- End of Table */
713 static void *
714 smbios_type_127_init(void *start)
715 {
716     struct smbios_type_127 *p = (struct smbios_type_127 *)start;
717
718     p->header.type = 127;
719     p->header.length = sizeof(struct smbios_type_127);
720     p->header.handle = 0x7f00;
721
722     start += sizeof(struct smbios_type_127);
723     *((u16 *)start) = 0;
724
725     return start + 2;
726 }
727
728 void smbios_init(void)
729 {
730     unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
731     char *start, *p, *q;
732     int memsize = GET_EBDA(ram_size) / (1024 * 1024);
733
734     bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
735     start = (void *)(bios_table_cur_addr);
736
737     p = (char *)start + sizeof(struct smbios_entry_point);
738
739 #define add_struct(fn) { \
740     q = (fn); \
741     nr_structs++; \
742     if ((q - p) > max_struct_size) \
743         max_struct_size = q - p; \
744     p = q; \
745 }
746
747     add_struct(smbios_type_0_init(p));
748     add_struct(smbios_type_1_init(p));
749     add_struct(smbios_type_3_init(p));
750     int smp_cpus = smp_probe();
751     for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
752         add_struct(smbios_type_4_init(p, cpu_num));
753     add_struct(smbios_type_16_init(p, memsize));
754     add_struct(smbios_type_17_init(p, memsize));
755     add_struct(smbios_type_19_init(p, memsize));
756     add_struct(smbios_type_20_init(p, memsize));
757     add_struct(smbios_type_32_init(p));
758     add_struct(smbios_type_127_init(p));
759
760 #undef add_struct
761
762     smbios_entry_point_init(
763         start, max_struct_size,
764         (p - (char *)start) - sizeof(struct smbios_entry_point),
765         (u32)(start + sizeof(struct smbios_entry_point)),
766         nr_structs);
767
768     bios_table_cur_addr += (p - (char *)start);
769
770     dprintf(1, "SMBIOS table addr=0x%08lx\n", (unsigned long)start);
771 }
772
773 void rombios32_init(void)
774 {
775     if (CONFIG_COREBOOT)
776         // XXX - not supported on coreboot yet.
777         return;
778
779     dprintf(1, "Starting rombios32\n");
780
781     cpu_probe();
782
783     pci_bios_init();
784
785     smm_init();
786
787     create_pirtable();
788
789     if (bios_table_cur_addr != 0) {
790
791         mptable_init();
792
793         uuid_probe();
794
795         smbios_init();
796
797         acpi_bios_init();
798
799         dprintf(1, "bios_table_cur_addr: 0x%08x\n", bios_table_cur_addr);
800         if (bios_table_cur_addr > bios_table_end_addr)
801             BX_PANIC("bios_table_end_addr overflow!\n");
802     }
803 }