coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
imd_cbmem.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <boot/coreboot_tables.h>
5 #include <bootmem.h>
6 #include <console/console.h>
7 #include <cbmem.h>
8 #include <imd.h>
9 #include <lib.h>
10 #include <types.h>
11 
12 /* The program loader passes on cbmem_top and the program entry point
13  has to fill in the _cbmem_top_ptr symbol based on the calling arguments. */
15 
16 static struct imd imd;
17 
18 void *cbmem_top(void)
19 {
20  if (ENV_ROMSTAGE) {
21  static void *top;
22  if (top)
23  return top;
24  top = cbmem_top_chipset();
25  return top;
26  }
28  return (void *)_cbmem_top_ptr;
29 
30  dead_code();
31 }
32 
34 
35 static inline const struct cbmem_entry *imd_to_cbmem(const struct imd_entry *e)
36 {
37  return (const struct cbmem_entry *)e;
38 }
39 
40 static inline const struct imd_entry *cbmem_to_imd(const struct cbmem_entry *e)
41 {
42  return (const struct imd_entry *)e;
43 }
44 
46 {
48 }
49 
50 static void cbmem_top_init_once(void)
51 {
52  /* Call one-time hook on expected cbmem init during boot. This sequence
53  assumes first init call is in romstage. */
54  if (!ENV_ROMSTAGE)
55  return;
56 
57  /* The test is only effective on X86 and when address hits UC memory. */
58  if (ENV_X86)
60 }
61 
63 {
64  const int no_recovery = 0;
65 
67 
69 
70  printk(BIOS_DEBUG, "CBMEM:\n");
71 
74  printk(BIOS_DEBUG, "failed.\n");
75  return;
76  }
77 
78  /* Add the specified range first */
79  if (size)
80  cbmem_add(id, size);
81 
82  /* Complete migration to CBMEM. */
83  cbmem_run_init_hooks(no_recovery);
84 
86 }
87 
89 {
90  return cbmem_initialize_id_size(0, 0);
91 }
92 
94 {
95  const int recovery = 1;
96 
98 
100 
101  if (imd_recover(&imd))
102  return 1;
103 
104  /*
105  * Lock the imd in romstage on a recovery. The assumption is that
106  * if the imd area was recovered in romstage then S3 resume path
107  * is being taken.
108  */
109  if (ENV_ROMSTAGE)
110  imd_lockdown(&imd);
111 
112  /* Add the specified range first */
113  if (size)
114  cbmem_add(id, size);
115 
116  /* Complete migration to CBMEM. */
117  cbmem_run_init_hooks(recovery);
118 
119  cbmem_initialized = 1;
120 
121  /* Recovery successful. */
122  return 0;
123 }
124 
125 int cbmem_recovery(int is_wakeup)
126 {
127  int rv = 0;
128  if (!is_wakeup)
130  else
131  rv = cbmem_initialize();
132  return rv;
133 }
134 
135 const struct cbmem_entry *cbmem_entry_add(u32 id, u64 size64)
136 {
137  const struct imd_entry *e;
138 
139  e = imd_entry_find_or_add(&imd, id, size64);
140 
141  return imd_to_cbmem(e);
142 }
143 
144 void *cbmem_add(u32 id, u64 size)
145 {
146  const struct imd_entry *e;
147 
148  e = imd_entry_find_or_add(&imd, id, size);
149 
150  if (e == NULL)
151  return NULL;
152 
153  return imd_entry_at(&imd, e);
154 }
155 
156 /* Retrieve a region provided a given id. */
157 const struct cbmem_entry *cbmem_entry_find(u32 id)
158 {
159  const struct imd_entry *e;
160 
161  e = imd_entry_find(&imd, id);
162 
163  return imd_to_cbmem(e);
164 }
165 
166 void *cbmem_find(u32 id)
167 {
168  const struct imd_entry *e;
169 
170  e = imd_entry_find(&imd, id);
171 
172  if (e == NULL)
173  return NULL;
174 
175  return imd_entry_at(&imd, e);
176 }
177 
178 /* Remove a reserved region. Returns 0 on success, < 0 on error. Note: A region
179  * cannot be removed unless it was the last one added. */
180 int cbmem_entry_remove(const struct cbmem_entry *entry)
181 {
182  return imd_entry_remove(&imd, cbmem_to_imd(entry));
183 }
184 
185 u64 cbmem_entry_size(const struct cbmem_entry *entry)
186 {
187  return imd_entry_size(cbmem_to_imd(entry));
188 }
189 
190 void *cbmem_entry_start(const struct cbmem_entry *entry)
191 {
192  return imd_entry_at(&imd, cbmem_to_imd(entry));
193 }
194 
196 {
197  void *baseptr = NULL;
198  size_t size = 0;
199 
200  cbmem_get_region(&baseptr, &size);
202 }
203 
204 void cbmem_get_region(void **baseptr, size_t *size)
205 {
206  imd_region_used(&imd, baseptr, size);
207 }
208 
209 #if ENV_PAYLOAD_LOADER || (CONFIG(EARLY_CBMEM_LIST) \
210  && (ENV_POSTCAR || ENV_ROMSTAGE))
211 /*
212  * -fdata-sections doesn't work so well on read only strings. They all
213  * get put in the same section even though those strings may never be
214  * referenced in the final binary.
215  */
216 void cbmem_list(void)
217 {
218  static const struct imd_lookup lookup[] = { CBMEM_ID_TO_NAME_TABLE };
219 
220  imd_print_entries(&imd, lookup, ARRAY_SIZE(lookup));
221 }
222 #endif
223 
225 {
226  struct imd_cursor cursor;
227 
228  if (imd_cursor_init(&imd, &cursor))
229  return;
230 
231  while (1) {
232  const struct imd_entry *e;
233  struct lb_cbmem_entry *lbe;
234  uint32_t id;
235 
236  e = imd_cursor_next(&cursor);
237 
238  if (e == NULL)
239  break;
240 
241  id = imd_entry_id(e);
242  /* Don't add these metadata entries. */
243  if (id == CBMEM_ID_IMD_ROOT || id == CBMEM_ID_IMD_SMALL)
244  continue;
245 
246  lbe = (struct lb_cbmem_entry *)lb_new_record(header);
247  lbe->tag = LB_TAG_CBMEM_ENTRY;
248  lbe->size = sizeof(*lbe);
249  lbe->address = (uintptr_t)imd_entry_at(&imd, e);
250  lbe->entry_size = imd_entry_size(e);
251  lbe->id = id;
252  }
253 }
struct arm64_kernel_header header
Definition: fit_payload.c:30
#define dead_code()
Definition: assert.h:89
@ BM_MEM_TABLE
Definition: bootmem.h:31
void bootmem_add_range(uint64_t start, uint64_t size, const enum bootmem_type tag)
Definition: bootmem.c:88
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define CBMEM_LG_ALIGN
Definition: cbmem.h:31
#define CBMEM_SM_ALIGN
Definition: cbmem.h:35
void cbmem_run_init_hooks(int is_recovery)
Definition: cbmem_common.c:6
void cbmem_list(void)
#define CBMEM_ROOT_MIN_SIZE
Definition: cbmem.h:30
#define CBMEM_SM_ROOT_SIZE
Definition: cbmem.h:34
#define CBMEM_ID_TO_NAME_TABLE
Definition: cbmem_id.h:84
#define CBMEM_ID_IMD_ROOT
Definition: cbmem_id.h:30
#define CBMEM_ID_IMD_SMALL
Definition: cbmem_id.h:31
@ LB_TAG_CBMEM_ENTRY
#define printk(level,...)
Definition: stdlib.h:16
void * cbmem_top_chipset(void)
Definition: romstage.c:108
const struct imd_entry * imd_entry_find(const struct imd *imd, uint32_t id)
Definition: imd.c:536
int imd_lockdown(struct imd *imd)
Definition: imd.c:463
const struct imd_entry * imd_cursor_next(struct imd_cursor *cursor)
Definition: imd.c:675
void * imd_entry_at(const struct imd *imd, const struct imd_entry *entry)
Definition: imd.c:568
int imd_entry_remove(const struct imd *imd, const struct imd_entry *entry)
Definition: imd.c:585
size_t imd_entry_size(const struct imd_entry *entry)
Definition: imd.c:563
uint32_t imd_entry_id(const struct imd_entry *entry)
Definition: imd.c:580
int imd_recover(struct imd *imd)
Definition: imd.c:428
int imd_region_used(struct imd *imd, void **base, size_t *size)
Definition: imd.c:480
int imd_print_entries(const struct imd *imd, const struct imd_lookup *lookup, size_t size)
Definition: imd.c:647
void imd_handle_init(struct imd *imd, void *upper_limit)
Definition: imd.c:352
int imd_create_tiered_empty(struct imd *imd, size_t lg_root_size, size_t lg_entry_align, size_t sm_root_size, size_t sm_entry_align)
Definition: imd.c:391
int imd_cursor_init(const struct imd *imd, struct imd_cursor *cursor)
Definition: imd.c:662
const struct imd_entry * imd_entry_find_or_add(const struct imd *imd, uint32_t id, size_t size)
Definition: imd.c:550
uintptr_t _cbmem_top_ptr
Definition: imd_cbmem.c:14
void cbmem_add_records_to_cbtable(struct lb_header *header)
Definition: imd_cbmem.c:224
int cbmem_initialize(void)
Definition: imd_cbmem.c:88
static const struct cbmem_entry * imd_to_cbmem(const struct imd_entry *e)
Definition: imd_cbmem.c:35
void cbmem_add_bootmem(void)
Definition: imd_cbmem.c:195
int cbmem_initialize_id_size(u32 id, u64 size)
Definition: imd_cbmem.c:93
void * cbmem_entry_start(const struct cbmem_entry *entry)
Definition: imd_cbmem.c:190
int cbmem_entry_remove(const struct cbmem_entry *entry)
Definition: imd_cbmem.c:180
const struct cbmem_entry * cbmem_entry_find(u32 id)
Definition: imd_cbmem.c:157
void * cbmem_top(void)
Definition: imd_cbmem.c:18
const struct cbmem_entry * cbmem_entry_add(u32 id, u64 size64)
Definition: imd_cbmem.c:135
static void cbmem_top_init_once(void)
Definition: imd_cbmem.c:50
int cbmem_initialized
Definition: imd_cbmem.c:33
void cbmem_get_region(void **baseptr, size_t *size)
Definition: imd_cbmem.c:204
void * cbmem_add(u32 id, u64 size)
Definition: imd_cbmem.c:144
int cbmem_recovery(int is_wakeup)
Definition: imd_cbmem.c:125
void cbmem_initialize_empty(void)
Definition: imd_cbmem.c:45
static const struct imd_entry * cbmem_to_imd(const struct cbmem_entry *e)
Definition: imd_cbmem.c:40
void cbmem_initialize_empty_id_size(u32 id, u64 size)
Definition: imd_cbmem.c:62
void * cbmem_find(u32 id)
Definition: imd_cbmem.c:166
u64 cbmem_entry_size(const struct cbmem_entry *entry)
Definition: imd_cbmem.c:185
struct lb_record * lb_new_record(struct lb_header *header)
void quick_ram_check_or_die(uintptr_t dst)
Definition: ramtest.c:177
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define ENV_X86
Definition: rules.h:248
#define ENV_RAMSTAGE
Definition: rules.h:150
#define ENV_ROMSTAGE
Definition: rules.h:149
#define ENV_POSTCAR
Definition: rules.h:154
#define NULL
Definition: stddef.h:19
uint64_t u64
Definition: stdint.h:54
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
Definition: nhlt.c:282
Definition: imd_private.h:14
uint32_t size
Definition: imd_private.h:18
Definition: imd.h:147
uint32_t size
uint32_t id
uint32_t tag
lb_uint64_t address
uint32_t entry_size