1*e7994858SSimon Glass /* 2*e7994858SSimon Glass * Read a coreboot rmodule and execute it. 3*e7994858SSimon Glass * The rmodule_header struct is from coreboot. 4*e7994858SSimon Glass * 5*e7994858SSimon Glass * Copyright (c) 2016 Google, Inc 6*e7994858SSimon Glass * 7*e7994858SSimon Glass * SPDX-License-Identifier: GPL-2.0 8*e7994858SSimon Glass */ 9*e7994858SSimon Glass 10*e7994858SSimon Glass #include <common.h> 11*e7994858SSimon Glass #include <errno.h> 12*e7994858SSimon Glass #include <asm/arch/pei_data.h> 13*e7994858SSimon Glass 14*e7994858SSimon Glass #define RMODULE_MAGIC 0xf8fe 15*e7994858SSimon Glass #define RMODULE_VERSION_1 1 16*e7994858SSimon Glass 17*e7994858SSimon Glass /* 18*e7994858SSimon Glass * All fields with '_offset' in the name are byte offsets into the flat blob. 19*e7994858SSimon Glass * The linker and the linker script takes are of assigning the values. 20*e7994858SSimon Glass */ 21*e7994858SSimon Glass struct rmodule_header { 22*e7994858SSimon Glass uint16_t magic; 23*e7994858SSimon Glass uint8_t version; 24*e7994858SSimon Glass uint8_t type; 25*e7994858SSimon Glass /* The payload represents the program's loadable code and data */ 26*e7994858SSimon Glass uint32_t payload_begin_offset; 27*e7994858SSimon Glass uint32_t payload_end_offset; 28*e7994858SSimon Glass /* Begin and of relocation information about the program module */ 29*e7994858SSimon Glass uint32_t relocations_begin_offset; 30*e7994858SSimon Glass uint32_t relocations_end_offset; 31*e7994858SSimon Glass /* 32*e7994858SSimon Glass * The starting address of the linked program. This address is vital 33*e7994858SSimon Glass * for determining relocation offsets as the relocation info and other 34*e7994858SSimon Glass * symbols (bss, entry point) need this value as a basis to calculate 35*e7994858SSimon Glass * the offsets. 36*e7994858SSimon Glass */ 37*e7994858SSimon Glass uint32_t module_link_start_address; 38*e7994858SSimon Glass /* 39*e7994858SSimon Glass * The module_program_size is the size of memory used while running 40*e7994858SSimon Glass * the program. The program is assumed to consume a contiguous amount 41*e7994858SSimon Glass * of memory 42*e7994858SSimon Glass */ 43*e7994858SSimon Glass uint32_t module_program_size; 44*e7994858SSimon Glass /* This is program's execution entry point */ 45*e7994858SSimon Glass uint32_t module_entry_point; 46*e7994858SSimon Glass /* 47*e7994858SSimon Glass * Optional parameter structure that can be used to pass data into 48*e7994858SSimon Glass * the module 49*e7994858SSimon Glass */ 50*e7994858SSimon Glass uint32_t parameters_begin; 51*e7994858SSimon Glass uint32_t parameters_end; 52*e7994858SSimon Glass /* BSS section information so the loader can clear the bss */ 53*e7994858SSimon Glass uint32_t bss_begin; 54*e7994858SSimon Glass uint32_t bss_end; 55*e7994858SSimon Glass /* Add some room for growth */ 56*e7994858SSimon Glass uint32_t padding[4]; 57*e7994858SSimon Glass } __packed; 58*e7994858SSimon Glass 59*e7994858SSimon Glass int cpu_run_reference_code(void) 60*e7994858SSimon Glass { 61*e7994858SSimon Glass struct pei_data _pei_data __aligned(8); 62*e7994858SSimon Glass struct pei_data *pei_data = &_pei_data; 63*e7994858SSimon Glass asmlinkage int (*func)(void *); 64*e7994858SSimon Glass struct rmodule_header *hdr; 65*e7994858SSimon Glass char *src, *dest; 66*e7994858SSimon Glass int ret, dummy; 67*e7994858SSimon Glass int size; 68*e7994858SSimon Glass 69*e7994858SSimon Glass hdr = (struct rmodule_header *)CONFIG_X86_REFCODE_ADDR; 70*e7994858SSimon Glass debug("Extracting code from rmodule at %p\n", hdr); 71*e7994858SSimon Glass if (hdr->magic != RMODULE_MAGIC) { 72*e7994858SSimon Glass debug("Invalid rmodule magic\n"); 73*e7994858SSimon Glass return -EINVAL; 74*e7994858SSimon Glass } 75*e7994858SSimon Glass if (hdr->module_link_start_address != 0) { 76*e7994858SSimon Glass debug("Link start address must be 0\n"); 77*e7994858SSimon Glass return -EPERM; 78*e7994858SSimon Glass } 79*e7994858SSimon Glass if (hdr->module_entry_point != 0) { 80*e7994858SSimon Glass debug("Entry point must be 0\n"); 81*e7994858SSimon Glass return -EPERM; 82*e7994858SSimon Glass } 83*e7994858SSimon Glass 84*e7994858SSimon Glass memset(pei_data, '\0', sizeof(struct pei_data)); 85*e7994858SSimon Glass broadwell_fill_pei_data(pei_data); 86*e7994858SSimon Glass mainboard_fill_pei_data(pei_data); 87*e7994858SSimon Glass pei_data->saved_data = (void *)&dummy; 88*e7994858SSimon Glass 89*e7994858SSimon Glass src = (char *)hdr + hdr->payload_begin_offset; 90*e7994858SSimon Glass dest = (char *)CONFIG_X86_REFCODE_RUN_ADDR; 91*e7994858SSimon Glass 92*e7994858SSimon Glass size = hdr->payload_end_offset - hdr->payload_begin_offset; 93*e7994858SSimon Glass debug("Copying refcode from %p to %p, size %x\n", src, dest, size); 94*e7994858SSimon Glass memcpy(dest, src, size); 95*e7994858SSimon Glass 96*e7994858SSimon Glass size = hdr->bss_end - hdr->bss_begin; 97*e7994858SSimon Glass debug("Zeroing BSS at %p, size %x\n", dest + hdr->bss_begin, size); 98*e7994858SSimon Glass memset(dest + hdr->bss_begin, '\0', size); 99*e7994858SSimon Glass 100*e7994858SSimon Glass func = (asmlinkage int (*)(void *))dest; 101*e7994858SSimon Glass debug("Running reference code at %p\n", func); 102*e7994858SSimon Glass #ifdef DEBUG 103*e7994858SSimon Glass print_buffer(CONFIG_X86_REFCODE_RUN_ADDR, (void *)func, 1, 0x40, 0); 104*e7994858SSimon Glass #endif 105*e7994858SSimon Glass ret = func(pei_data); 106*e7994858SSimon Glass if (ret != 0) { 107*e7994858SSimon Glass debug("Reference code returned %d\n", ret); 108*e7994858SSimon Glass return -EL2HLT; 109*e7994858SSimon Glass } 110*e7994858SSimon Glass debug("Refereence code completed\n"); 111*e7994858SSimon Glass 112*e7994858SSimon Glass return 0; 113*e7994858SSimon Glass } 114