mb/google/parrot: Fix smbus subsystem ID
[coreboot.git] / payloads / libpayload / libc / coreboot.c
blob3c49484064e1a0bed0803e0eec978ae997d00bb6
1 /*
3 * Copyright (C) 2008 Advanced Micro Devices, Inc.
4 * Copyright (C) 2009 coresystems GmbH
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include <libpayload-config.h>
31 #include <libpayload.h>
32 #include <commonlib/bsd/cbmem_id.h>
33 #include <coreboot_tables.h>
34 #include <stdint.h>
37 * The code in this file applies to all coreboot architectures. Some coreboot
38 * table tags are architecture specific, they are handled by their respective
39 * cb_parse_arch_specific() functions.
42 /* === Parsing code === */
43 /* This is the generic parsing code. */
45 static void cb_parse_memory(void *ptr, struct sysinfo_t *info)
47 struct cb_memory *mem = ptr;
48 int count = MEM_RANGE_COUNT(mem);
49 int i;
51 if (count > SYSINFO_MAX_MEM_RANGES)
52 count = SYSINFO_MAX_MEM_RANGES;
54 info->n_memranges = 0;
56 for (i = 0; i < count; i++) {
57 struct cb_memory_range *range = MEM_RANGE_PTR(mem, i);
59 #if CONFIG(LP_MEMMAP_RAM_ONLY)
60 if (range->type != CB_MEM_RAM)
61 continue;
62 #endif
64 info->memrange[info->n_memranges].base = range->start;
65 info->memrange[info->n_memranges].size = range->size;
66 info->memrange[info->n_memranges].type = range->type;
68 info->n_memranges++;
72 static void cb_parse_serial(void *ptr, struct sysinfo_t *info)
74 info->cb_serial = virt_to_phys(ptr);
77 static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
79 struct lb_range *vbnv = (struct lb_range *)ptr;
81 info->vbnv_start = vbnv->range_start;
82 info->vbnv_size = vbnv->range_size;
85 static void cb_parse_mmc_info(unsigned char *ptr, struct sysinfo_t *info)
87 struct cb_mmc_info *mmc_info = (struct cb_mmc_info *)ptr;
89 info->mmc_early_wake_status = mmc_info->early_cmd1_status;
92 static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
94 int i;
95 struct cb_gpios *gpios = (struct cb_gpios *)ptr;
97 info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
98 (gpios->count) : SYSINFO_MAX_GPIOS;
100 for (i = 0; i < info->num_gpios; i++)
101 info->gpios[i] = gpios->gpios[i];
104 static void cb_parse_mac_addresses(unsigned char *ptr,
105 struct sysinfo_t *info)
107 struct cb_macs *macs = (struct cb_macs *)ptr;
108 int i;
110 info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
111 macs->count : ARRAY_SIZE(info->macs);
113 for (i = 0; i < info->num_macs; i++)
114 info->macs[i] = macs->mac_addrs[i];
117 static void cb_parse_board_config(unsigned char *ptr, struct sysinfo_t *info)
119 struct cb_board_config *const config = (struct cb_board_config *)ptr;
120 info->fw_config = config->fw_config;
121 info->board_id = config->board_id;
122 info->ram_code = config->ram_code;
123 info->sku_id = config->sku_id;
126 #if CONFIG(LP_NVRAM)
127 static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
129 /* ptr is already virtual, but we want to keep physical addresses */
130 info->cmos_option_table = virt_to_phys(ptr);
133 static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
135 struct cb_cmos_checksum *cmos_cksum = ptr;
136 info->cmos_range_start = cmos_cksum->range_start;
137 info->cmos_range_end = cmos_cksum->range_end;
138 info->cmos_checksum_location = cmos_cksum->location;
140 #endif
142 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
143 static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
145 info->framebuffer = *(struct cb_framebuffer *)ptr;
147 #endif
149 static void cb_parse_string(const void *const ptr, uintptr_t *const info)
151 /* ptr is already virtual (str->string just an offset to that),
152 but we want to keep physical addresses */
153 const struct cb_string *const str = ptr;
154 *info = virt_to_phys(str->string);
157 static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
159 struct lb_range *ramoops = (struct lb_range *)ptr;
161 info->ramoops_buffer = ramoops->range_start;
162 info->ramoops_buffer_size = ramoops->range_size;
165 static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
167 struct lb_range *mtc = (struct lb_range *)ptr;
169 info->mtc_start = mtc->range_start;
170 info->mtc_size = mtc->range_size;
173 static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
175 struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
177 info->spi_flash.size = flash->flash_size;
178 info->spi_flash.sector_size = flash->sector_size;
179 info->spi_flash.erase_cmd = flash->erase_cmd;
181 if (flash->mmap_count == 0)
182 return;
184 info->spi_flash.mmap_window_count = MIN(flash->mmap_count, SYSINFO_MAX_MMAP_WINDOWS);
185 memcpy(info->spi_flash.mmap_table, flash->mmap_table,
186 info->spi_flash.mmap_window_count * sizeof(struct flash_mmap_window));
189 static void cb_parse_boot_media_params(unsigned char *ptr,
190 struct sysinfo_t *info)
192 struct cb_boot_media_params *const bmp =
193 (struct cb_boot_media_params *)ptr;
194 info->fmap_offset = bmp->fmap_offset;
195 info->cbfs_offset = bmp->cbfs_offset;
196 info->cbfs_size = bmp->cbfs_size;
197 info->boot_media_size = bmp->boot_media_size;
200 #if CONFIG(LP_TIMER_RDTSC)
201 static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info)
203 const struct cb_tsc_info *tsc_info = ptr;
205 if (tsc_info->freq_khz == 0)
206 return;
208 /* Honor the TSC frequency passed to the payload. */
209 info->cpu_khz = tsc_info->freq_khz;
211 #endif
213 static void cb_parse_cbmem_entry(void *ptr, struct sysinfo_t *info)
215 const struct cb_cbmem_entry *cbmem_entry = ptr;
217 if (cbmem_entry->size != sizeof(*cbmem_entry))
218 return;
220 switch (cbmem_entry->id) {
221 case CBMEM_ID_ACPI_CNVS:
222 info->acpi_cnvs = cbmem_entry->address;
223 break;
224 case CBMEM_ID_ACPI_GNVS:
225 info->acpi_gnvs = cbmem_entry->address;
226 break;
227 case CBMEM_ID_SMBIOS:
228 info->smbios = cbmem_entry->address;
229 break;
230 case CBMEM_ID_CBFS_RO_MCACHE:
231 info->cbfs_ro_mcache_offset = cbmem_entry->address;
232 info->cbfs_ro_mcache_size = cbmem_entry->entry_size;
233 break;
234 case CBMEM_ID_CBFS_RW_MCACHE:
235 info->cbfs_rw_mcache_offset = cbmem_entry->address;
236 info->cbfs_rw_mcache_size = cbmem_entry->entry_size;
237 break;
238 case CBMEM_ID_CONSOLE:
239 info->cbmem_cons = cbmem_entry->address;
240 break;
241 case CBMEM_ID_MRCDATA:
242 info->mrc_cache = cbmem_entry->address;
243 break;
244 case CBMEM_ID_VBOOT_WORKBUF:
245 info->vboot_workbuf = cbmem_entry->address;
246 break;
247 case CBMEM_ID_TIMESTAMP:
248 info->tstamp_table = cbmem_entry->address;
249 break;
250 case CBMEM_ID_VPD:
251 info->chromeos_vpd = cbmem_entry->address;
252 break;
253 case CBMEM_ID_FMAP:
254 info->fmap_cache = cbmem_entry->address;
255 break;
256 case CBMEM_ID_WIFI_CALIBRATION:
257 info->wifi_calibration = cbmem_entry->address;
258 break;
259 case CBMEM_ID_TYPE_C_INFO:
260 info->type_c_info = cbmem_entry->address;
261 break;
262 case CBMEM_ID_MEM_CHIP_INFO:
263 info->mem_chip_base = cbmem_entry->address;
264 break;
265 default:
266 break;
270 static void cb_parse_pcie(void *ptr, struct sysinfo_t *info)
272 const struct cb_pcie *pcie = ptr;
274 info->pcie_ctrl_base = pcie->ctrl_base;
277 static void cb_parse_rsdp(void *ptr, struct sysinfo_t *info)
279 const struct cb_acpi_rsdp *cb_acpi_rsdp = ptr;
280 info->acpi_rsdp = cb_acpi_rsdp->rsdp_pointer;
283 int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
285 struct cb_header *header;
286 unsigned char *ptr = addr;
287 void *forward;
288 int i;
290 for (i = 0; i < len; i += 16, ptr += 16) {
291 header = (struct cb_header *)ptr;
292 if (!strncmp((const char *)header->signature, "LBIO", 4))
293 break;
296 /* We walked the entire space and didn't find anything. */
297 if (i >= len)
298 return -1;
300 /* Make sure the checksums match. */
301 if (ipchksum((u16 *) header, sizeof(*header)) != 0)
302 return -1;
304 if (!header->table_bytes)
305 return 0;
307 if (ipchksum((u16 *) (ptr + sizeof(*header)),
308 header->table_bytes) != header->table_checksum)
309 return -1;
311 info->cb_header = virt_to_phys(header);
313 /* Initialize IDs as undefined in case they don't show up in table. */
314 info->board_id = UNDEFINED_STRAPPING_ID;
315 info->ram_code = UNDEFINED_STRAPPING_ID;
316 info->sku_id = UNDEFINED_STRAPPING_ID;
317 info->fw_config = UNDEFINED_FW_CONFIG;
319 /* Now, walk the tables. */
320 ptr += header->header_bytes;
322 for (i = 0; i < header->table_entries; i++) {
323 struct cb_record *rec = (struct cb_record *)ptr;
325 /* We only care about a few tags here (maybe more later). */
326 switch (rec->tag) {
327 case CB_TAG_FORWARD:
328 forward = phys_to_virt((void *)(unsigned long)
329 ((struct cb_forward *)rec)->forward);
330 return cb_parse_header(forward, len, info);
331 case CB_TAG_MEMORY:
332 cb_parse_memory(ptr, info);
333 break;
334 case CB_TAG_SERIAL:
335 cb_parse_serial(ptr, info);
336 break;
337 case CB_TAG_VERSION:
338 cb_parse_string(ptr, &info->cb_version);
339 break;
340 case CB_TAG_EXTRA_VERSION:
341 cb_parse_string(ptr, &info->extra_version);
342 break;
343 case CB_TAG_BUILD:
344 cb_parse_string(ptr, &info->build);
345 break;
346 case CB_TAG_COMPILE_TIME:
347 cb_parse_string(ptr, &info->compile_time);
348 break;
349 case CB_TAG_COMPILE_BY:
350 cb_parse_string(ptr, &info->compile_by);
351 break;
352 case CB_TAG_COMPILE_HOST:
353 cb_parse_string(ptr, &info->compile_host);
354 break;
355 case CB_TAG_COMPILE_DOMAIN:
356 cb_parse_string(ptr, &info->compile_domain);
357 break;
358 case CB_TAG_COMPILER:
359 cb_parse_string(ptr, &info->compiler);
360 break;
361 case CB_TAG_LINKER:
362 cb_parse_string(ptr, &info->linker);
363 break;
364 case CB_TAG_ASSEMBLER:
365 cb_parse_string(ptr, &info->assembler);
366 break;
367 #if CONFIG(LP_NVRAM)
368 case CB_TAG_CMOS_OPTION_TABLE:
369 cb_parse_optiontable(ptr, info);
370 break;
371 case CB_TAG_OPTION_CHECKSUM:
372 cb_parse_checksum(ptr, info);
373 break;
374 #endif
375 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
376 // FIXME we should warn on serial if coreboot set up a
377 // framebuffer buf the payload does not know about it.
378 case CB_TAG_FRAMEBUFFER:
379 cb_parse_framebuffer(ptr, info);
380 break;
381 #endif
382 case CB_TAG_MAINBOARD:
383 info->cb_mainboard = virt_to_phys(ptr);
384 break;
385 case CB_TAG_GPIO:
386 cb_parse_gpios(ptr, info);
387 break;
388 case CB_TAG_VBNV:
389 cb_parse_vbnv(ptr, info);
390 break;
391 case CB_TAG_MAC_ADDRS:
392 cb_parse_mac_addresses(ptr, info);
393 break;
394 case CB_TAG_SERIALNO:
395 cb_parse_string(ptr, &info->serialno);
396 break;
397 case CB_TAG_BOARD_CONFIG:
398 cb_parse_board_config(ptr, info);
399 break;
400 case CB_TAG_RAM_OOPS:
401 cb_parse_ramoops(ptr, info);
402 break;
403 case CB_TAG_SPI_FLASH:
404 cb_parse_spi_flash(ptr, info);
405 break;
406 case CB_TAG_MMC_INFO:
407 cb_parse_mmc_info(ptr, info);
408 break;
409 case CB_TAG_MTC:
410 cb_parse_mtc(ptr, info);
411 break;
412 case CB_TAG_BOOT_MEDIA_PARAMS:
413 cb_parse_boot_media_params(ptr, info);
414 break;
415 case CB_TAG_CBMEM_ENTRY:
416 cb_parse_cbmem_entry(ptr, info);
417 break;
418 #if CONFIG(LP_TIMER_RDTSC)
419 case CB_TAG_TSC_INFO:
420 cb_parse_tsc_info(ptr, info);
421 break;
422 #endif
423 case CB_TAG_ACPI_RSDP:
424 cb_parse_rsdp(ptr, info);
425 break;
426 case CB_TAG_PCIE:
427 cb_parse_pcie(ptr, info);
428 break;
429 default:
430 cb_parse_arch_specific(rec, info);
431 break;
434 ptr += rec->size;
437 return 0;