Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / src / fw / biostables.c
1 // Support for manipulating bios tables (pir, mptable, acpi, smbios).
2 //
3 // Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "byteorder.h" // le32_to_cpu
8 #include "config.h" // CONFIG_*
9 #include "malloc.h" // malloc_fseg
10 #include "output.h" // dprintf
11 #include "hw/pci.h" // pci_config_writeb
12 #include "std/acpi.h" // struct rsdp_descriptor
13 #include "std/mptable.h" // MPTABLE_SIGNATURE
14 #include "std/pirtable.h" // struct pir_header
15 #include "std/smbios.h" // struct smbios_entry_point
16 #include "romfile.h"
17 #include "string.h" // memcpy
18 #include "util.h" // copy_table
19 #include "x86.h" // outb
20
21 struct pir_header *PirAddr VARFSEG;
22
23 void
24 copy_pir(void *pos)
25 {
26     struct pir_header *p = pos;
27     if (p->signature != PIR_SIGNATURE)
28         return;
29     if (PirAddr)
30         return;
31     if (p->size < sizeof(*p))
32         return;
33     if (checksum(pos, p->size) != 0)
34         return;
35     void *newpos = malloc_fseg(p->size);
36     if (!newpos) {
37         warn_noalloc();
38         return;
39     }
40     dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
41     memcpy(newpos, pos, p->size);
42     PirAddr = newpos;
43 }
44
45 void
46 copy_mptable(void *pos)
47 {
48     struct mptable_floating_s *p = pos;
49     if (p->signature != MPTABLE_SIGNATURE)
50         return;
51     if (!p->physaddr)
52         return;
53     if (checksum(pos, sizeof(*p)) != 0)
54         return;
55     u32 length = p->length * 16;
56     u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
57     // Allocate final memory location.  (In theory the config
58     // structure can go in high memory, but Linux kernels before
59     // v2.6.30 crash with that.)
60     struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
61     if (!newpos) {
62         warn_noalloc();
63         return;
64     }
65     dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
66     memcpy(newpos, pos, length);
67     newpos->physaddr = (u32)newpos + length;
68     newpos->checksum -= checksum(newpos, sizeof(*newpos));
69     memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
70 }
71
72
73 /****************************************************************
74  * ACPI
75  ****************************************************************/
76
77 static int
78 get_acpi_rsdp_length(void *pos, unsigned size)
79 {
80     struct rsdp_descriptor *p = pos;
81     if (p->signature != RSDP_SIGNATURE)
82         return -1;
83     u32 length = 20;
84     if (length > size)
85         return -1;
86     if (checksum(pos, length) != 0)
87         return -1;
88     if (p->revision > 1) {
89         length = p->length;
90         if (length > size)
91             return -1;
92         if (checksum(pos, length) != 0)
93             return -1;
94     }
95     return length;
96 }
97
98 struct rsdp_descriptor *RsdpAddr;
99
100 void
101 copy_acpi_rsdp(void *pos)
102 {
103     if (RsdpAddr)
104         return;
105     int length = get_acpi_rsdp_length(pos, -1);
106     if (length < 0)
107         return;
108     void *newpos = malloc_fseg(length);
109     if (!newpos) {
110         warn_noalloc();
111         return;
112     }
113     dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
114     memcpy(newpos, pos, length);
115     RsdpAddr = newpos;
116 }
117
118 void *find_acpi_rsdp(void)
119 {
120     extern u8 zonefseg_start[], zonefseg_end[];
121     unsigned long start = (unsigned long)zonefseg_start;
122     unsigned long end = (unsigned long)zonefseg_end;
123     unsigned long pos;
124
125     for (pos = ALIGN(start, 0x10); pos <= ALIGN_DOWN(end, 0x10); pos += 0x10)
126         if (get_acpi_rsdp_length((void *)pos, end - pos) >= 0)
127             return (void *)pos;
128
129     return NULL;
130 }
131
132 static struct fadt_descriptor_rev1 *
133 find_fadt(void)
134 {
135     dprintf(4, "rsdp=%p\n", RsdpAddr);
136     if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
137         return NULL;
138     struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
139     dprintf(4, "rsdt=%p\n", rsdt);
140     if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
141         return NULL;
142     void *end = (void*)rsdt + rsdt->length;
143     int i;
144     for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
145         struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
146         if (!fadt || fadt->signature != FACP_SIGNATURE)
147             continue;
148         dprintf(4, "fadt=%p\n", fadt);
149         return fadt;
150     }
151     dprintf(4, "no fadt found\n");
152     return NULL;
153 }
154
155 u32
156 find_resume_vector(void)
157 {
158     struct fadt_descriptor_rev1 *fadt = find_fadt();
159     if (!fadt)
160         return 0;
161     struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
162     dprintf(4, "facs=%p\n", facs);
163     if (! facs || facs->signature != FACS_SIGNATURE)
164         return 0;
165     // Found it.
166     dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
167     return facs->firmware_waking_vector;
168 }
169
170 static struct acpi_20_generic_address acpi_reset_reg;
171 static u8 acpi_reset_val;
172 u32 acpi_pm1a_cnt VARFSEG;
173 u16 acpi_pm_base = 0xb000;
174
175 #define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff)
176
177 void
178 acpi_reboot(void)
179 {
180     // Check it passed the sanity checks in acpi_set_reset_reg() and was set
181     if (acpi_reset_reg.register_bit_width != 8)
182         return;
183
184     u64 addr = le64_to_cpu(acpi_reset_reg.address);
185
186     dprintf(1, "ACPI hard reset %d:%llx (%x)\n",
187             acpi_reset_reg.address_space_id, addr, acpi_reset_val);
188
189     switch (acpi_reset_reg.address_space_id) {
190     case 0: // System Memory
191         writeb((void *)(u32)addr, acpi_reset_val);
192         break;
193     case 1: // System I/O
194         outb(acpi_reset_val, addr);
195         break;
196     case 2: // PCI config space
197         pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val);
198         break;
199     }
200 }
201
202 static void
203 acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val)
204 {
205     if (!reg || reg->address_space_id > 2 ||
206         reg->register_bit_width != 8 || reg->register_bit_offset)
207         return;
208
209     acpi_reset_reg = *reg;
210     acpi_reset_val = val;
211 }
212
213 void
214 find_acpi_features(void)
215 {
216     struct fadt_descriptor_rev1 *fadt = find_fadt();
217     if (!fadt)
218         return;
219     u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk);
220     u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk);
221     dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
222     if (pm_tmr)
223         pmtimer_setup(pm_tmr);
224     if (pm1a_cnt)
225         acpi_pm1a_cnt = pm1a_cnt;
226
227     // Theoretically we should check the 'reset_reg_sup' flag, but Windows
228     // doesn't and thus nobody seems to *set* it. If the table is large enough
229     // to include it, let the sanity checks in acpi_set_reset_reg() suffice.
230     if (fadt->length >= 129) {
231         void *p = fadt;
232         acpi_set_reset_reg(p + 116, *(u8 *)(p + 128));
233     }
234 }
235
236
237 /****************************************************************
238  * SMBIOS
239  ****************************************************************/
240
241 // Iterator for each sub-table in the smbios blob.
242 void *
243 smbios_next(struct smbios_entry_point *smbios, void *prev)
244 {
245     if (!smbios)
246         return NULL;
247     void *start = (void*)smbios->structure_table_address;
248     void *end = start + smbios->structure_table_length;
249
250     if (!prev) {
251         prev = start;
252     } else {
253         struct smbios_structure_header *hdr = prev;
254         if (prev + sizeof(*hdr) > end)
255             return NULL;
256         prev += hdr->length + 2;
257         while (prev < end && (*(u8*)(prev-1) != '\0' || *(u8*)(prev-2) != '\0'))
258             prev++;
259     }
260     struct smbios_structure_header *hdr = prev;
261     if (prev >= end || prev + sizeof(*hdr) >= end || prev + hdr->length >= end)
262         return NULL;
263     return prev;
264 }
265
266 struct smbios_entry_point *SMBiosAddr;
267
268 void
269 copy_smbios(void *pos)
270 {
271     if (SMBiosAddr)
272         return;
273     struct smbios_entry_point *p = pos;
274     if (memcmp(p->anchor_string, "_SM_", 4))
275         return;
276     if (checksum(pos, 0x10) != 0)
277         return;
278     if (memcmp(p->intermediate_anchor_string, "_DMI_", 5))
279         return;
280     if (checksum(pos+0x10, p->length-0x10) != 0)
281         return;
282     struct smbios_entry_point *newpos = malloc_fseg(p->length);
283     if (!newpos) {
284         warn_noalloc();
285         return;
286     }
287     dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos);
288     memcpy(newpos, pos, p->length);
289     SMBiosAddr = newpos;
290 }
291
292 void
293 display_uuid(void)
294 {
295     struct smbios_type_1 *tbl = smbios_next(SMBiosAddr, NULL);
296     int minlen = offsetof(struct smbios_type_1, uuid) + sizeof(tbl->uuid);
297     for (; tbl; tbl = smbios_next(SMBiosAddr, tbl))
298         if (tbl->header.type == 1 && tbl->header.length >= minlen) {
299             u8 *uuid = tbl->uuid;
300             u8 empty_uuid[sizeof(tbl->uuid)] = { 0 };
301             if (memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0)
302                 return;
303
304             printf("Machine UUID"
305                    " %02x%02x%02x%02x"
306                    "-%02x%02x"
307                    "-%02x%02x"
308                    "-%02x%02x"
309                    "-%02x%02x%02x%02x%02x%02x\n"
310                    , uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3]
311                    , uuid[ 4], uuid[ 5]
312                    , uuid[ 6], uuid[ 7]
313                    , uuid[ 8], uuid[ 9]
314                    , uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
315             return;
316         }
317 }
318
319 #define set_str_field_or_skip(type, field, value)                       \
320     do {                                                                \
321         int size = (value != NULL) ? strlen(value) + 1 : 0;             \
322         if (size > 1) {                                                 \
323             memcpy(end, value, size);                                   \
324             end += size;                                                \
325             p->field = ++str_index;                                     \
326         } else {                                                        \
327             p->field = 0;                                               \
328         }                                                               \
329     } while (0)
330
331 static void *
332 smbios_new_type_0(void *start,
333                   const char *vendor, const char *version, const char *date)
334 {
335     struct smbios_type_0 *p = (struct smbios_type_0 *)start;
336     char *end = (char *)start + sizeof(struct smbios_type_0);
337     int str_index = 0;
338
339     p->header.type = 0;
340     p->header.length = sizeof(struct smbios_type_0);
341     p->header.handle = 0;
342
343     set_str_field_or_skip(0, vendor_str, vendor);
344     set_str_field_or_skip(0, bios_version_str, version);
345     p->bios_starting_address_segment = 0xe800;
346     set_str_field_or_skip(0, bios_release_date_str, date);
347
348     p->bios_rom_size = 0; /* FIXME */
349
350     /* BIOS characteristics not supported */
351     memset(p->bios_characteristics, 0, 8);
352     p->bios_characteristics[0] = 0x08;
353
354     /* Enable targeted content distribution (needed for SVVP) */
355     p->bios_characteristics_extension_bytes[0] = 0;
356     p->bios_characteristics_extension_bytes[1] = 4;
357
358     p->system_bios_major_release = 0;
359     p->system_bios_minor_release = 0;
360     p->embedded_controller_major_release = 0xFF;
361     p->embedded_controller_minor_release = 0xFF;
362
363     *end = 0;
364     end++;
365     if (!str_index) {
366         *end = 0;
367         end++;
368     }
369
370     return end;
371 }
372
373 #define BIOS_NAME "SeaBIOS"
374 #define BIOS_DATE "04/01/2014"
375
376 static int
377 smbios_romfile_setup(void)
378 {
379     struct romfile_s *f_anchor = romfile_find("etc/smbios/smbios-anchor");
380     struct romfile_s *f_tables = romfile_find("etc/smbios/smbios-tables");
381     struct smbios_entry_point ep;
382     struct smbios_type_0 *t0;
383     u16 qtables_len, need_t0 = 1;
384     u8 *qtables, *tables;
385
386     if (!f_anchor || !f_tables || f_anchor->size != sizeof(ep))
387         return 0;
388
389     f_anchor->copy(f_anchor, &ep, f_anchor->size);
390
391     if (f_tables->size != ep.structure_table_length)
392         return 0;
393
394     qtables = malloc_tmphigh(f_tables->size);
395     if (!qtables) {
396         warn_noalloc();
397         return 0;
398     }
399     f_tables->copy(f_tables, qtables, f_tables->size);
400     ep.structure_table_address = (u32)qtables; /* for smbios_next(), below */
401
402     /* did we get a type 0 structure ? */
403     for (t0 = smbios_next(&ep, NULL); t0; t0 = smbios_next(&ep, t0))
404         if (t0->header.type == 0) {
405             need_t0 = 0;
406             break;
407         }
408
409     qtables_len = ep.structure_table_length;
410     if (need_t0) {
411         /* common case: add our own type 0, with 3 strings and 4 '\0's */
412         u16 t0_len = sizeof(struct smbios_type_0) + strlen(BIOS_NAME) +
413                      strlen(VERSION) + strlen(BIOS_DATE) + 4;
414         ep.structure_table_length += t0_len;
415         if (t0_len > ep.max_structure_size)
416             ep.max_structure_size = t0_len;
417         ep.number_of_structures++;
418     }
419
420     /* allocate final blob and record its address in the entry point */
421     if (ep.structure_table_length > BUILD_MAX_SMBIOS_FSEG)
422         tables = malloc_high(ep.structure_table_length);
423     else
424         tables = malloc_fseg(ep.structure_table_length);
425     if (!tables) {
426         warn_noalloc();
427         free(qtables);
428         return 0;
429     }
430     ep.structure_table_address = (u32)tables;
431
432     /* populate final blob */
433     if (need_t0)
434         tables = smbios_new_type_0(tables, BIOS_NAME, VERSION, BIOS_DATE);
435     memcpy(tables, qtables, qtables_len);
436     free(qtables);
437
438     /* finalize entry point */
439     ep.checksum -= checksum(&ep, 0x10);
440     ep.intermediate_checksum -= checksum((void *)&ep + 0x10, ep.length - 0x10);
441
442     copy_smbios(&ep);
443     return 1;
444 }
445
446 void
447 smbios_setup(void)
448 {
449     if (smbios_romfile_setup())
450       return;
451     smbios_legacy_setup();
452 }
453
454 void
455 copy_table(void *pos)
456 {
457     copy_pir(pos);
458     copy_mptable(pos);
459     copy_acpi_rsdp(pos);
460     copy_smbios(pos);
461 }