1 /* 2 * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <vbe.h> 9 #include <asm/acpi_s3.h> 10 #include <asm/coreboot_tables.h> 11 #include <asm/e820.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 int high_table_reserve(void) 16 { 17 /* adjust stack pointer to reserve space for configuration tables */ 18 gd->arch.high_table_limit = gd->start_addr_sp; 19 gd->start_addr_sp -= CONFIG_HIGH_TABLE_SIZE; 20 gd->arch.high_table_ptr = gd->start_addr_sp; 21 22 /* clear the memory */ 23 #ifdef CONFIG_HAVE_ACPI_RESUME 24 if (gd->arch.prev_sleep_state != ACPI_S3) 25 #endif 26 memset((void *)gd->arch.high_table_ptr, 0, 27 CONFIG_HIGH_TABLE_SIZE); 28 29 gd->start_addr_sp &= ~0xf; 30 31 return 0; 32 } 33 34 void *high_table_malloc(size_t bytes) 35 { 36 u32 new_ptr; 37 void *ptr; 38 39 new_ptr = gd->arch.high_table_ptr + bytes; 40 if (new_ptr >= gd->arch.high_table_limit) 41 return NULL; 42 ptr = (void *)gd->arch.high_table_ptr; 43 gd->arch.high_table_ptr = new_ptr; 44 45 return ptr; 46 } 47 48 /** 49 * cb_table_init() - initialize a coreboot table header 50 * 51 * This fills in the coreboot table header signature and the header bytes. 52 * Other fields are set to zero. 53 * 54 * @cbh: coreboot table header address 55 */ 56 static void cb_table_init(struct cb_header *cbh) 57 { 58 memset(cbh, 0, sizeof(struct cb_header)); 59 memcpy(cbh->signature, "LBIO", 4); 60 cbh->header_bytes = sizeof(struct cb_header); 61 } 62 63 /** 64 * cb_table_add_entry() - add a coreboot table entry 65 * 66 * This increases the coreboot table entry size with added table entry length 67 * and increases entry count by 1. 68 * 69 * @cbh: coreboot table header address 70 * @cbr: to be added table entry address 71 * @return: pointer to next table entry address 72 */ 73 static u32 cb_table_add_entry(struct cb_header *cbh, struct cb_record *cbr) 74 { 75 cbh->table_bytes += cbr->size; 76 cbh->table_entries++; 77 78 return (u32)cbr + cbr->size; 79 } 80 81 /** 82 * cb_table_finalize() - finalize the coreboot table 83 * 84 * This calculates the checksum for all coreboot table entries as well as 85 * the checksum for the coreboot header itself. 86 * 87 * @cbh: coreboot table header address 88 */ 89 static void cb_table_finalize(struct cb_header *cbh) 90 { 91 struct cb_record *cbr = (struct cb_record *)(cbh + 1); 92 93 cbh->table_checksum = compute_ip_checksum(cbr, cbh->table_bytes); 94 cbh->header_checksum = compute_ip_checksum(cbh, cbh->header_bytes); 95 } 96 97 void write_coreboot_table(u32 addr, struct memory_area *cfg_tables) 98 { 99 struct cb_header *cbh = (struct cb_header *)addr; 100 struct cb_record *cbr; 101 struct cb_memory *mem; 102 struct cb_memory_range *map; 103 struct e820entry e820[32]; 104 struct cb_framebuffer *fb; 105 struct vesa_mode_info *vesa; 106 int i, num; 107 108 cb_table_init(cbh); 109 cbr = (struct cb_record *)(cbh + 1); 110 111 /* 112 * Two type of coreboot table entries are generated by us. 113 * They are 'struct cb_memory' and 'struct cb_framebuffer'. 114 */ 115 116 /* populate memory map table */ 117 mem = (struct cb_memory *)cbr; 118 mem->tag = CB_TAG_MEMORY; 119 map = mem->map; 120 121 /* first install e820 defined memory maps */ 122 num = install_e820_map(ARRAY_SIZE(e820), e820); 123 for (i = 0; i < num; i++) { 124 map->start.lo = e820[i].addr & 0xffffffff; 125 map->start.hi = e820[i].addr >> 32; 126 map->size.lo = e820[i].size & 0xffffffff; 127 map->size.hi = e820[i].size >> 32; 128 map->type = e820[i].type; 129 map++; 130 } 131 132 /* then install all configuration tables */ 133 while (cfg_tables->size) { 134 map->start.lo = cfg_tables->start & 0xffffffff; 135 map->start.hi = cfg_tables->start >> 32; 136 map->size.lo = cfg_tables->size & 0xffffffff; 137 map->size.hi = cfg_tables->size >> 32; 138 map->type = CB_MEM_TABLE; 139 map++; 140 num++; 141 cfg_tables++; 142 } 143 mem->size = num * sizeof(struct cb_memory_range) + 144 sizeof(struct cb_record); 145 cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr); 146 147 /* populate framebuffer table if we have sane vesa info */ 148 vesa = &mode_info.vesa; 149 if (vesa->x_resolution && vesa->y_resolution) { 150 fb = (struct cb_framebuffer *)cbr; 151 fb->tag = CB_TAG_FRAMEBUFFER; 152 fb->size = sizeof(struct cb_framebuffer); 153 154 fb->x_resolution = vesa->x_resolution; 155 fb->y_resolution = vesa->y_resolution; 156 fb->bits_per_pixel = vesa->bits_per_pixel; 157 fb->bytes_per_line = vesa->bytes_per_scanline; 158 fb->physical_address = vesa->phys_base_ptr; 159 fb->red_mask_size = vesa->red_mask_size; 160 fb->red_mask_pos = vesa->red_mask_pos; 161 fb->green_mask_size = vesa->green_mask_size; 162 fb->green_mask_pos = vesa->green_mask_pos; 163 fb->blue_mask_size = vesa->blue_mask_size; 164 fb->blue_mask_pos = vesa->blue_mask_pos; 165 fb->reserved_mask_size = vesa->reserved_mask_size; 166 fb->reserved_mask_pos = vesa->reserved_mask_pos; 167 168 cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr); 169 } 170 171 cb_table_finalize(cbh); 172 } 173