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