1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
226f9a9b7SBin Meng /*
326f9a9b7SBin Meng * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
426f9a9b7SBin Meng */
526f9a9b7SBin Meng
626f9a9b7SBin Meng #include <common.h>
726f9a9b7SBin Meng #include <vbe.h>
895e50dd1SBin Meng #include <asm/acpi_s3.h>
926f9a9b7SBin Meng #include <asm/coreboot_tables.h>
1026f9a9b7SBin Meng #include <asm/e820.h>
1126f9a9b7SBin Meng
12789b6dceSBin Meng DECLARE_GLOBAL_DATA_PTR;
13789b6dceSBin Meng
high_table_reserve(void)14789b6dceSBin Meng int high_table_reserve(void)
15789b6dceSBin Meng {
16789b6dceSBin Meng /* adjust stack pointer to reserve space for configuration tables */
17789b6dceSBin Meng gd->arch.high_table_limit = gd->start_addr_sp;
18789b6dceSBin Meng gd->start_addr_sp -= CONFIG_HIGH_TABLE_SIZE;
19789b6dceSBin Meng gd->arch.high_table_ptr = gd->start_addr_sp;
20789b6dceSBin Meng
21789b6dceSBin Meng /* clear the memory */
2295e50dd1SBin Meng #ifdef CONFIG_HAVE_ACPI_RESUME
2395e50dd1SBin Meng if (gd->arch.prev_sleep_state != ACPI_S3)
2495e50dd1SBin Meng #endif
2595e50dd1SBin Meng memset((void *)gd->arch.high_table_ptr, 0,
2695e50dd1SBin Meng CONFIG_HIGH_TABLE_SIZE);
27789b6dceSBin Meng
28789b6dceSBin Meng gd->start_addr_sp &= ~0xf;
29789b6dceSBin Meng
30789b6dceSBin Meng return 0;
31789b6dceSBin Meng }
32789b6dceSBin Meng
high_table_malloc(size_t bytes)33789b6dceSBin Meng void *high_table_malloc(size_t bytes)
34789b6dceSBin Meng {
35789b6dceSBin Meng u32 new_ptr;
36789b6dceSBin Meng void *ptr;
37789b6dceSBin Meng
38789b6dceSBin Meng new_ptr = gd->arch.high_table_ptr + bytes;
39789b6dceSBin Meng if (new_ptr >= gd->arch.high_table_limit)
40789b6dceSBin Meng return NULL;
41789b6dceSBin Meng ptr = (void *)gd->arch.high_table_ptr;
42789b6dceSBin Meng gd->arch.high_table_ptr = new_ptr;
43789b6dceSBin Meng
44789b6dceSBin Meng return ptr;
45789b6dceSBin Meng }
46789b6dceSBin Meng
4726f9a9b7SBin Meng /**
4826f9a9b7SBin Meng * cb_table_init() - initialize a coreboot table header
4926f9a9b7SBin Meng *
5026f9a9b7SBin Meng * This fills in the coreboot table header signature and the header bytes.
5126f9a9b7SBin Meng * Other fields are set to zero.
5226f9a9b7SBin Meng *
5326f9a9b7SBin Meng * @cbh: coreboot table header address
5426f9a9b7SBin Meng */
cb_table_init(struct cb_header * cbh)5526f9a9b7SBin Meng static void cb_table_init(struct cb_header *cbh)
5626f9a9b7SBin Meng {
5726f9a9b7SBin Meng memset(cbh, 0, sizeof(struct cb_header));
5826f9a9b7SBin Meng memcpy(cbh->signature, "LBIO", 4);
5926f9a9b7SBin Meng cbh->header_bytes = sizeof(struct cb_header);
6026f9a9b7SBin Meng }
6126f9a9b7SBin Meng
6226f9a9b7SBin Meng /**
6326f9a9b7SBin Meng * cb_table_add_entry() - add a coreboot table entry
6426f9a9b7SBin Meng *
6526f9a9b7SBin Meng * This increases the coreboot table entry size with added table entry length
6626f9a9b7SBin Meng * and increases entry count by 1.
6726f9a9b7SBin Meng *
6826f9a9b7SBin Meng * @cbh: coreboot table header address
6926f9a9b7SBin Meng * @cbr: to be added table entry address
7026f9a9b7SBin Meng * @return: pointer to next table entry address
7126f9a9b7SBin Meng */
cb_table_add_entry(struct cb_header * cbh,struct cb_record * cbr)7226f9a9b7SBin Meng static u32 cb_table_add_entry(struct cb_header *cbh, struct cb_record *cbr)
7326f9a9b7SBin Meng {
7426f9a9b7SBin Meng cbh->table_bytes += cbr->size;
7526f9a9b7SBin Meng cbh->table_entries++;
7626f9a9b7SBin Meng
7726f9a9b7SBin Meng return (u32)cbr + cbr->size;
7826f9a9b7SBin Meng }
7926f9a9b7SBin Meng
8026f9a9b7SBin Meng /**
8126f9a9b7SBin Meng * cb_table_finalize() - finalize the coreboot table
8226f9a9b7SBin Meng *
8326f9a9b7SBin Meng * This calculates the checksum for all coreboot table entries as well as
8426f9a9b7SBin Meng * the checksum for the coreboot header itself.
8526f9a9b7SBin Meng *
8626f9a9b7SBin Meng * @cbh: coreboot table header address
8726f9a9b7SBin Meng */
cb_table_finalize(struct cb_header * cbh)8826f9a9b7SBin Meng static void cb_table_finalize(struct cb_header *cbh)
8926f9a9b7SBin Meng {
9026f9a9b7SBin Meng struct cb_record *cbr = (struct cb_record *)(cbh + 1);
9126f9a9b7SBin Meng
9226f9a9b7SBin Meng cbh->table_checksum = compute_ip_checksum(cbr, cbh->table_bytes);
9326f9a9b7SBin Meng cbh->header_checksum = compute_ip_checksum(cbh, cbh->header_bytes);
9426f9a9b7SBin Meng }
9526f9a9b7SBin Meng
write_coreboot_table(u32 addr,struct memory_area * cfg_tables)9626f9a9b7SBin Meng void write_coreboot_table(u32 addr, struct memory_area *cfg_tables)
9726f9a9b7SBin Meng {
9826f9a9b7SBin Meng struct cb_header *cbh = (struct cb_header *)addr;
9926f9a9b7SBin Meng struct cb_record *cbr;
10026f9a9b7SBin Meng struct cb_memory *mem;
10126f9a9b7SBin Meng struct cb_memory_range *map;
10245519924SBin Meng struct e820_entry e820[32];
10326f9a9b7SBin Meng struct cb_framebuffer *fb;
10426f9a9b7SBin Meng struct vesa_mode_info *vesa;
10526f9a9b7SBin Meng int i, num;
10626f9a9b7SBin Meng
10726f9a9b7SBin Meng cb_table_init(cbh);
10826f9a9b7SBin Meng cbr = (struct cb_record *)(cbh + 1);
10926f9a9b7SBin Meng
11026f9a9b7SBin Meng /*
11126f9a9b7SBin Meng * Two type of coreboot table entries are generated by us.
11226f9a9b7SBin Meng * They are 'struct cb_memory' and 'struct cb_framebuffer'.
11326f9a9b7SBin Meng */
11426f9a9b7SBin Meng
11526f9a9b7SBin Meng /* populate memory map table */
11626f9a9b7SBin Meng mem = (struct cb_memory *)cbr;
11726f9a9b7SBin Meng mem->tag = CB_TAG_MEMORY;
11826f9a9b7SBin Meng map = mem->map;
11926f9a9b7SBin Meng
12026f9a9b7SBin Meng /* first install e820 defined memory maps */
12126f9a9b7SBin Meng num = install_e820_map(ARRAY_SIZE(e820), e820);
12226f9a9b7SBin Meng for (i = 0; i < num; i++) {
12326f9a9b7SBin Meng map->start.lo = e820[i].addr & 0xffffffff;
12426f9a9b7SBin Meng map->start.hi = e820[i].addr >> 32;
12526f9a9b7SBin Meng map->size.lo = e820[i].size & 0xffffffff;
12626f9a9b7SBin Meng map->size.hi = e820[i].size >> 32;
12726f9a9b7SBin Meng map->type = e820[i].type;
12826f9a9b7SBin Meng map++;
12926f9a9b7SBin Meng }
13026f9a9b7SBin Meng
13126f9a9b7SBin Meng /* then install all configuration tables */
13226f9a9b7SBin Meng while (cfg_tables->size) {
13326f9a9b7SBin Meng map->start.lo = cfg_tables->start & 0xffffffff;
13426f9a9b7SBin Meng map->start.hi = cfg_tables->start >> 32;
13526f9a9b7SBin Meng map->size.lo = cfg_tables->size & 0xffffffff;
13626f9a9b7SBin Meng map->size.hi = cfg_tables->size >> 32;
13726f9a9b7SBin Meng map->type = CB_MEM_TABLE;
13826f9a9b7SBin Meng map++;
13926f9a9b7SBin Meng num++;
14026f9a9b7SBin Meng cfg_tables++;
14126f9a9b7SBin Meng }
14226f9a9b7SBin Meng mem->size = num * sizeof(struct cb_memory_range) +
14326f9a9b7SBin Meng sizeof(struct cb_record);
14426f9a9b7SBin Meng cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr);
14526f9a9b7SBin Meng
14626f9a9b7SBin Meng /* populate framebuffer table if we have sane vesa info */
14726f9a9b7SBin Meng vesa = &mode_info.vesa;
14826f9a9b7SBin Meng if (vesa->x_resolution && vesa->y_resolution) {
14926f9a9b7SBin Meng fb = (struct cb_framebuffer *)cbr;
15026f9a9b7SBin Meng fb->tag = CB_TAG_FRAMEBUFFER;
15126f9a9b7SBin Meng fb->size = sizeof(struct cb_framebuffer);
15226f9a9b7SBin Meng
15326f9a9b7SBin Meng fb->x_resolution = vesa->x_resolution;
15426f9a9b7SBin Meng fb->y_resolution = vesa->y_resolution;
15526f9a9b7SBin Meng fb->bits_per_pixel = vesa->bits_per_pixel;
15626f9a9b7SBin Meng fb->bytes_per_line = vesa->bytes_per_scanline;
15726f9a9b7SBin Meng fb->physical_address = vesa->phys_base_ptr;
15826f9a9b7SBin Meng fb->red_mask_size = vesa->red_mask_size;
15926f9a9b7SBin Meng fb->red_mask_pos = vesa->red_mask_pos;
16026f9a9b7SBin Meng fb->green_mask_size = vesa->green_mask_size;
16126f9a9b7SBin Meng fb->green_mask_pos = vesa->green_mask_pos;
16226f9a9b7SBin Meng fb->blue_mask_size = vesa->blue_mask_size;
16326f9a9b7SBin Meng fb->blue_mask_pos = vesa->blue_mask_pos;
16426f9a9b7SBin Meng fb->reserved_mask_size = vesa->reserved_mask_size;
16526f9a9b7SBin Meng fb->reserved_mask_pos = vesa->reserved_mask_pos;
16626f9a9b7SBin Meng
16726f9a9b7SBin Meng cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr);
16826f9a9b7SBin Meng }
16926f9a9b7SBin Meng
17026f9a9b7SBin Meng cb_table_finalize(cbh);
17126f9a9b7SBin Meng }
172