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