2 * This file is part of the coreboot project.
4 * Copyright (C) 2003-2004 Eric Biederman
5 * Copyright (C) 2005-2010 coresystems GmbH
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <console/console.h>
19 #include <console/uart.h>
20 #include <ip_checksum.h>
21 #include <boot/coreboot_tables.h>
22 #include <boot_device.h>
26 #include <device/device.h>
32 #include <spi_flash.h>
33 #if CONFIG_USE_OPTION_TABLE
34 #include <option_table.h>
37 #if CONFIG_HAVE_ACPI_TABLES
38 #include <arch/acpi.h>
40 #include <vendorcode/google/chromeos/chromeos.h>
41 #include <vendorcode/google/chromeos/gnvs.h>
44 #include <cpu/x86/mtrr.h>
47 static struct lb_header
*lb_table_init(unsigned long addr
)
49 struct lb_header
*header
;
51 /* 16 byte align the address */
55 header
= (void *)addr
;
56 header
->signature
[0] = 'L';
57 header
->signature
[1] = 'B';
58 header
->signature
[2] = 'I';
59 header
->signature
[3] = 'O';
60 header
->header_bytes
= sizeof(*header
);
61 header
->header_checksum
= 0;
62 header
->table_bytes
= 0;
63 header
->table_checksum
= 0;
64 header
->table_entries
= 0;
68 static struct lb_record
*lb_first_record(struct lb_header
*header
)
70 struct lb_record
*rec
;
71 rec
= (void *)(((char *)header
) + sizeof(*header
));
75 static struct lb_record
*lb_last_record(struct lb_header
*header
)
77 struct lb_record
*rec
;
78 rec
= (void *)(((char *)header
) + sizeof(*header
) + header
->table_bytes
);
82 struct lb_record
*lb_new_record(struct lb_header
*header
)
84 struct lb_record
*rec
;
85 rec
= lb_last_record(header
);
86 if (header
->table_entries
) {
87 header
->table_bytes
+= rec
->size
;
89 rec
= lb_last_record(header
);
90 header
->table_entries
++;
91 rec
->tag
= LB_TAG_UNUSED
;
92 rec
->size
= sizeof(*rec
);
96 static struct lb_memory
*lb_memory(struct lb_header
*header
)
98 struct lb_record
*rec
;
99 struct lb_memory
*mem
;
100 rec
= lb_new_record(header
);
101 mem
= (struct lb_memory
*)rec
;
102 mem
->tag
= LB_TAG_MEMORY
;
103 mem
->size
= sizeof(*mem
);
107 void lb_add_serial(struct lb_serial
*new_serial
, void *data
)
109 struct lb_header
*header
= (struct lb_header
*)data
;
110 struct lb_serial
*serial
;
112 serial
= (struct lb_serial
*)lb_new_record(header
);
113 serial
->tag
= LB_TAG_SERIAL
;
114 serial
->size
= sizeof(*serial
);
115 serial
->type
= new_serial
->type
;
116 serial
->baseaddr
= new_serial
->baseaddr
;
117 serial
->baud
= new_serial
->baud
;
118 serial
->regwidth
= new_serial
->regwidth
;
121 void lb_add_console(uint16_t consoletype
, void *data
)
123 struct lb_header
*header
= (struct lb_header
*)data
;
124 struct lb_console
*console
;
126 console
= (struct lb_console
*)lb_new_record(header
);
127 console
->tag
= LB_TAG_CONSOLE
;
128 console
->size
= sizeof(*console
);
129 console
->type
= consoletype
;
132 void __attribute__((weak
)) lb_framebuffer(struct lb_header
*header
)
134 #if CONFIG_FRAMEBUFFER_KEEP_VESA_MODE || CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
135 void fill_lb_framebuffer(struct lb_framebuffer
*framebuffer
);
136 int vbe_mode_info_valid(void);
138 // If there isn't any mode info to put in the table, don't ask for it
139 // to be filled with junk.
140 if (!vbe_mode_info_valid())
142 struct lb_framebuffer
*framebuffer
;
143 framebuffer
= (struct lb_framebuffer
*)lb_new_record(header
);
144 fill_lb_framebuffer(framebuffer
);
145 framebuffer
->tag
= LB_TAG_FRAMEBUFFER
;
146 framebuffer
->size
= sizeof(*framebuffer
);
150 void fill_lb_gpio(struct lb_gpio
*gpio
, int num
,
151 int polarity
, const char *name
, int value
)
153 memset(gpio
, 0, sizeof(*gpio
));
155 gpio
->polarity
= polarity
;
158 strncpy((char *)gpio
->name
, name
, GPIO_MAX_NAME_LENGTH
);
162 static void lb_gpios(struct lb_header
*header
)
164 struct lb_gpios
*gpios
;
166 gpios
= (struct lb_gpios
*)lb_new_record(header
);
167 gpios
->tag
= LB_TAG_GPIO
;
168 gpios
->size
= sizeof(*gpios
);
170 fill_lb_gpios(gpios
);
173 static void lb_vdat(struct lb_header
*header
)
175 #if CONFIG_HAVE_ACPI_TABLES
176 struct lb_range
*vdat
;
178 vdat
= (struct lb_range
*)lb_new_record(header
);
179 vdat
->tag
= LB_TAG_VDAT
;
180 vdat
->size
= sizeof(*vdat
);
181 acpi_get_vdat_info(&vdat
->range_start
, &vdat
->range_size
);
185 static void lb_vbnv(struct lb_header
*header
)
187 #if CONFIG_PC80_SYSTEM
188 struct lb_range
*vbnv
;
190 vbnv
= (struct lb_range
*)lb_new_record(header
);
191 vbnv
->tag
= LB_TAG_VBNV
;
192 vbnv
->size
= sizeof(*vbnv
);
193 vbnv
->range_start
= CONFIG_VBNV_OFFSET
+ 14;
194 vbnv
->range_size
= CONFIG_VBNV_SIZE
;
198 #if CONFIG_VBOOT_VERIFY_FIRMWARE
199 static void lb_vboot_handoff(struct lb_header
*header
)
203 struct lb_range
*vbho
;
205 if (vboot_get_handoff_info(&addr
, &size
))
208 vbho
= (struct lb_range
*)lb_new_record(header
);
209 vbho
->tag
= LB_TAB_VBOOT_HANDOFF
;
210 vbho
->size
= sizeof(*vbho
);
211 vbho
->range_start
= (intptr_t)addr
;
212 vbho
->range_size
= size
;
215 static inline void lb_vboot_handoff(struct lb_header
*header
) {}
216 #endif /* CONFIG_VBOOT_VERIFY_FIRMWARE */
217 #endif /* CONFIG_CHROMEOS */
219 static void lb_board_id(struct lb_header
*header
)
221 #if CONFIG_BOARD_ID_AUTO || CONFIG_BOARD_ID_MANUAL
222 struct lb_board_id
*bid
;
224 bid
= (struct lb_board_id
*)lb_new_record(header
);
226 bid
->tag
= LB_TAG_BOARD_ID
;
227 bid
->size
= sizeof(*bid
);
228 bid
->board_id
= board_id();
232 static void lb_boot_media_params(struct lb_header
*header
)
234 struct lb_boot_media_params
*bmp
;
235 struct cbfs_props props
;
236 const struct region_device
*boot_dev
;
237 struct region_device fmrd
;
241 if (cbfs_boot_region_properties(&props
))
244 boot_dev
= boot_device_ro();
245 if (boot_dev
== NULL
)
248 bmp
= (struct lb_boot_media_params
*)lb_new_record(header
);
249 bmp
->tag
= LB_TAG_BOOT_MEDIA_PARAMS
;
250 bmp
->size
= sizeof(*bmp
);
252 bmp
->cbfs_offset
= props
.offset
;
253 bmp
->cbfs_size
= props
.size
;
254 bmp
->boot_media_size
= region_device_sz(boot_dev
);
256 bmp
->fmap_offset
= ~(uint64_t)0;
257 if (find_fmap_directory(&fmrd
) == 0) {
258 bmp
->fmap_offset
= region_device_offset(&fmrd
);
262 static void lb_ram_code(struct lb_header
*header
)
264 #if IS_ENABLED(CONFIG_RAM_CODE_SUPPORT)
265 struct lb_ram_code
*code
;
267 code
= (struct lb_ram_code
*)lb_new_record(header
);
269 code
->tag
= LB_TAG_RAM_CODE
;
270 code
->size
= sizeof(*code
);
271 code
->ram_code
= ram_code();
275 static void add_cbmem_pointers(struct lb_header
*header
)
278 * These CBMEM sections' addresses are included in the coreboot table
279 * with the appropriate tags.
281 const struct section_id
{
285 {CBMEM_ID_TIMESTAMP
, LB_TAG_TIMESTAMPS
},
286 {CBMEM_ID_CONSOLE
, LB_TAG_CBMEM_CONSOLE
},
287 {CBMEM_ID_ACPI_GNVS
, LB_TAG_ACPI_GNVS
},
288 {CBMEM_ID_WIFI_CALIBRATION
, LB_TAG_WIFI_CALIBRATION
}
292 for (i
= 0; i
< ARRAY_SIZE(section_ids
); i
++) {
293 const struct section_id
*sid
= section_ids
+ i
;
294 struct lb_cbmem_ref
*cbmem_ref
;
295 void *cbmem_addr
= cbmem_find(sid
->cbmem_id
);
298 continue; /* This section is not present */
300 cbmem_ref
= (struct lb_cbmem_ref
*)lb_new_record(header
);
302 printk(BIOS_ERR
, "No more room in coreboot table!\n");
305 cbmem_ref
->tag
= sid
->table_tag
;
306 cbmem_ref
->size
= sizeof(*cbmem_ref
);
307 cbmem_ref
->cbmem_addr
= (unsigned long)cbmem_addr
;
311 static struct lb_mainboard
*lb_mainboard(struct lb_header
*header
)
313 struct lb_record
*rec
;
314 struct lb_mainboard
*mainboard
;
315 rec
= lb_new_record(header
);
316 mainboard
= (struct lb_mainboard
*)rec
;
317 mainboard
->tag
= LB_TAG_MAINBOARD
;
319 mainboard
->size
= (sizeof(*mainboard
) +
320 strlen(mainboard_vendor
) + 1 +
321 strlen(mainboard_part_number
) + 1 +
324 mainboard
->vendor_idx
= 0;
325 mainboard
->part_number_idx
= strlen(mainboard_vendor
) + 1;
327 memcpy(mainboard
->strings
+ mainboard
->vendor_idx
,
328 mainboard_vendor
, strlen(mainboard_vendor
) + 1);
329 memcpy(mainboard
->strings
+ mainboard
->part_number_idx
,
330 mainboard_part_number
, strlen(mainboard_part_number
) + 1);
335 #if CONFIG_USE_OPTION_TABLE
336 static struct cmos_checksum
*lb_cmos_checksum(struct lb_header
*header
)
338 struct lb_record
*rec
;
339 struct cmos_checksum
*cmos_checksum
;
340 rec
= lb_new_record(header
);
341 cmos_checksum
= (struct cmos_checksum
*)rec
;
342 cmos_checksum
->tag
= LB_TAG_OPTION_CHECKSUM
;
344 cmos_checksum
->size
= (sizeof(*cmos_checksum
));
346 cmos_checksum
->range_start
= LB_CKS_RANGE_START
* 8;
347 cmos_checksum
->range_end
= ( LB_CKS_RANGE_END
* 8 ) + 7;
348 cmos_checksum
->location
= LB_CKS_LOC
* 8;
349 cmos_checksum
->type
= CHECKSUM_PCBIOS
;
351 return cmos_checksum
;
355 static void lb_strings(struct lb_header
*header
)
357 static const struct {
361 { LB_TAG_VERSION
, coreboot_version
, },
362 { LB_TAG_EXTRA_VERSION
, coreboot_extra_version
, },
363 { LB_TAG_BUILD
, coreboot_build
, },
364 { LB_TAG_COMPILE_TIME
, coreboot_compile_time
, },
367 for(i
= 0; i
< ARRAY_SIZE(strings
); i
++) {
368 struct lb_string
*rec
;
370 rec
= (struct lb_string
*)lb_new_record(header
);
371 len
= strlen(strings
[i
].string
);
372 rec
->tag
= strings
[i
].tag
;
373 rec
->size
= (sizeof(*rec
) + len
+ 1 + 3) & ~3;
374 memcpy(rec
->string
, strings
[i
].string
, len
+1);
379 static void lb_record_version_timestamp(struct lb_header
*header
)
381 struct lb_timestamp
*rec
;
382 rec
= (struct lb_timestamp
*)lb_new_record(header
);
383 rec
->tag
= LB_TAG_VERSION_TIMESTAMP
;
384 rec
->size
= sizeof(*rec
);
385 rec
->timestamp
= coreboot_version_timestamp
;
388 void __attribute__((weak
)) lb_board(struct lb_header
*header
) { /* NOOP */ }
390 static struct lb_forward
*lb_forward(struct lb_header
*header
, struct lb_header
*next_header
)
392 struct lb_record
*rec
;
393 struct lb_forward
*forward
;
394 rec
= lb_new_record(header
);
395 forward
= (struct lb_forward
*)rec
;
396 forward
->tag
= LB_TAG_FORWARD
;
397 forward
->size
= sizeof(*forward
);
398 forward
->forward
= (uint64_t)(unsigned long)next_header
;
402 static unsigned long lb_table_fini(struct lb_header
*head
)
404 struct lb_record
*rec
, *first_rec
;
405 rec
= lb_last_record(head
);
406 if (head
->table_entries
) {
407 head
->table_bytes
+= rec
->size
;
410 first_rec
= lb_first_record(head
);
411 head
->table_checksum
= compute_ip_checksum(first_rec
, head
->table_bytes
);
412 head
->header_checksum
= 0;
413 head
->header_checksum
= compute_ip_checksum(head
, sizeof(*head
));
415 "Wrote coreboot table at: %p, 0x%x bytes, checksum %x\n",
416 head
, head
->table_bytes
, head
->table_checksum
);
417 return (unsigned long)rec
+ rec
->size
;
420 unsigned long write_coreboot_table(
421 unsigned long low_table_start
, unsigned long low_table_end
,
422 unsigned long rom_table_start
, unsigned long rom_table_end
)
424 struct lb_header
*head
;
426 if (low_table_start
|| low_table_end
) {
427 printk(BIOS_DEBUG
, "Writing table forward entry at 0x%08lx\n",
429 head
= lb_table_init(low_table_end
);
430 lb_forward(head
, (struct lb_header
*)rom_table_end
);
432 low_table_end
= (unsigned long) lb_table_fini(head
);
433 printk(BIOS_DEBUG
, "Table forward entry ends at 0x%08lx.\n",
435 low_table_end
= ALIGN(low_table_end
, 4096);
436 printk(BIOS_DEBUG
, "... aligned to 0x%08lx\n", low_table_end
);
439 printk(BIOS_DEBUG
, "Writing coreboot table at 0x%08lx\n",
442 head
= lb_table_init(rom_table_end
);
443 rom_table_end
= (unsigned long)head
;
444 printk(BIOS_DEBUG
, "rom_table_end = 0x%08lx\n", rom_table_end
);
445 rom_table_end
= ALIGN(rom_table_end
, (64 * 1024));
446 printk(BIOS_DEBUG
, "... aligned to 0x%08lx\n", rom_table_end
);
448 #if CONFIG_USE_OPTION_TABLE
450 struct cmos_option_table
*option_table
=
451 cbfs_boot_map_with_leak("cmos_layout.bin",
452 CBFS_COMPONENT_CMOS_LAYOUT
, NULL
);
454 struct lb_record
*rec_dest
= lb_new_record(head
);
455 /* Copy the option config table, it's already a lb_record... */
456 memcpy(rec_dest
, option_table
, option_table
->size
);
457 /* Create cmos checksum entry in coreboot table */
458 lb_cmos_checksum(head
);
460 printk(BIOS_ERR
, "cmos_layout.bin could not be found!\n");
465 /* Initialize the memory map at boot time. */
468 if (low_table_start
|| low_table_end
) {
469 uint64_t size
= low_table_end
- low_table_start
;
470 /* Record the mptable and the the lb_table.
471 * (This will be adjusted later) */
472 bootmem_add_range(low_table_start
, size
, LB_MEM_TABLE
);
475 /* Record the pirq table, acpi tables, and maybe the mptable. However,
476 * these only need to be added when the rom_table is sitting below
477 * 1MiB. If it isn't that means high tables are being written.
478 * The code below handles high tables correctly. */
479 if (rom_table_end
<= (1 << 20)) {
480 uint64_t size
= rom_table_end
- rom_table_start
;
481 bootmem_add_range(rom_table_start
, size
, LB_MEM_TABLE
);
484 /* No other memory areas can be added after the memory table has been
485 * committed as the entries won't show up in the serialize mem table. */
486 bootmem_write_memory_table(lb_memory(head
));
488 /* Record our motherboard */
491 /* Record the serial ports and consoles */
492 #if CONFIG_CONSOLE_SERIAL
495 #if CONFIG_CONSOLE_USB
496 lb_add_console(LB_TAG_CONSOLE_EHCI
, head
);
499 /* Record our various random string information */
501 lb_record_version_timestamp(head
);
502 /* Record our framebuffer */
503 lb_framebuffer(head
);
506 /* Record our GPIO settings (ChromeOS specific) */
509 /* pass along the VDAT buffer address */
512 /* pass along VBNV offsets in CMOS */
515 /* pass along the vboot_handoff address. */
516 lb_vboot_handoff(head
);
519 /* Add board ID if available */
522 /* Add RAM config if available */
525 #if IS_ENABLED(CONFIG_SPI_FLASH)
526 /* Add SPI flash description if available */
530 add_cbmem_pointers(head
);
532 /* Add board-specific table entries, if any. */
535 #if IS_ENABLED(CONFIG_CHROMEOS_RAMOOPS)
539 lb_boot_media_params(head
);
541 /* Remember where my valid memory ranges are */
542 return lb_table_fini(head
);