uboot/arch/x86/lib/coreboot_table.c
<<
>>
Prefs
   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
  13DECLARE_GLOBAL_DATA_PTR;
  14
  15int 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
  34void *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 */
  56static 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 */
  73static 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 */
  89static 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
  97void 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