coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
memory_clear.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #if ENV_X86
4 #include <cpu/x86/pae.h>
5 #else
6 #define memset_pae(a, b, c, d, e) 0
7 #define MEMSET_PAE_PGTL_ALIGN 0
8 #define MEMSET_PAE_PGTL_SIZE 0
9 #define MEMSET_PAE_PGTL_SIZE 0
10 #define MEMSET_PAE_VMEM_ALIGN 0
11 #endif
12 
13 #include <memrange.h>
14 #include <bootmem.h>
15 #include <bootstate.h>
16 #include <symbols.h>
17 #include <console/console.h>
18 #include <arch/memory_clear.h>
19 #include <string.h>
20 #include <security/memory/memory.h>
21 #include <cbmem.h>
22 #include <acpi/acpi.h>
23 
24 /* Helper to find free space for memset_pae. */
26  const resource_t align,
27  const resource_t size)
28 {
29  const struct range_entry *r;
30 
31  /* Find a spot for virtual memory address */
32  memranges_each_entry(r, mem) {
33  if (range_entry_tag(r) != BM_MEM_RAM)
34  continue;
35 
36  if (ALIGN_UP(range_entry_base(r) + size, align) + size >
37  range_entry_end(r))
38  continue;
39 
40  return ALIGN_UP(range_entry_base(r) + size, align);
41  }
42  printk(BIOS_ERR, "%s: Couldn't find free memory range\n", __func__);
43 
44  return 0;
45 }
46 
47 /*
48  * Clears all memory regions marked as BM_MEM_RAM.
49  * Uses memset_pae if the memory region can't be accessed by memset and
50  * architecture is x86.
51  *
52  * @return 0 on success, 1 on error
53  */
54 static void clear_memory(void *unused)
55 {
56  const struct range_entry *r;
57  struct memranges mem;
58  uintptr_t pgtbl, vmem_addr;
59 
60  if (acpi_is_wakeup_s3())
61  return;
62 
64  return;
65 
66  /* FSP1.0 is marked as MMIO and won't appear here */
67 
74  BM_MEM_RAM);
75 
76  /* Add reserved entries */
77  void *baseptr = NULL;
78  size_t size = 0;
79 
80  /* Only skip CBMEM, stage program, stack and heap are included there. */
81 
82  cbmem_get_region(&baseptr, &size);
83  memranges_insert(&mem, (uintptr_t)baseptr, size, BM_MEM_TABLE);
84 
85  if (ENV_X86) {
86  /* Find space for PAE enabled memset */
89 
90  /* Don't touch page tables while clearing */
92  BM_MEM_TABLE);
93 
96 
97  printk(BIOS_SPEW, "%s: pgtbl at %p, virt memory at %p\n",
98  __func__, (void *)pgtbl, (void *)vmem_addr);
99  }
100 
101  /* Now clear all usable DRAM */
102  memranges_each_entry(r, &mem) {
103  if (range_entry_tag(r) != BM_MEM_RAM)
104  continue;
105  printk(BIOS_DEBUG, "%s: Clearing DRAM %016llx-%016llx\n",
106  __func__, range_entry_base(r), range_entry_end(r));
107 
108  /* Does regular memset work? */
109  if (sizeof(resource_t) == sizeof(void *) ||
110  !(range_entry_end(r) >> (sizeof(void *) * 8))) {
111  /* fastpath */
112  memset((void *)(uintptr_t)range_entry_base(r), 0,
113  range_entry_size(r));
114  }
115  /* Use PAE if available */
116  else if (ENV_X86) {
117  if (memset_pae(range_entry_base(r), 0,
118  range_entry_size(r), (void *)pgtbl,
119  (void *)vmem_addr))
120  printk(BIOS_ERR, "%s: Failed to memset "
121  "memory\n", __func__);
122  } else {
123  printk(BIOS_ERR, "%s: Failed to memset memory\n",
124  __func__);
125  }
126  }
127 
128  if (ENV_X86) {
129  /* Clear previously skipped memory reserved for pagetables */
130  printk(BIOS_DEBUG, "%s: Clearing DRAM %016lx-%016lx\n",
131  __func__, pgtbl, pgtbl + MEMSET_PAE_PGTL_SIZE);
132 
133  memset((void *)pgtbl, 0, MEMSET_PAE_PGTL_SIZE);
134  }
135 
136  memranges_teardown(&mem);
137 }
138 
139 /* After DEV_INIT as MTRRs needs to be configured on x86 */
static int acpi_is_wakeup_s3(void)
Definition: acpi.h:9
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
@ BM_MEM_RAM
Definition: bootmem.h:23
@ BM_MEM_TABLE
Definition: bootmem.h:31
@ BS_DEV_INIT
Definition: bootstate.h:83
@ BS_ON_EXIT
Definition: bootstate.h:96
#define ALIGN_UP(x, a)
Definition: helpers.h:17
void cbmem_get_region(void **baseptr, size_t *size)
Definition: imd_cbmem.c:204
#define printk(level,...)
Definition: stdlib.h:16
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
#define MEMSET_PAE_PGTL_SIZE
Definition: memory_clear.c:9
#define memset_pae(a, b, c, d, e)
Definition: memory_clear.c:6
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, clear_memory, NULL)
static uintptr_t get_free_memory_range(struct memranges *mem, const resource_t align, const resource_t size)
Definition: memory_clear.c:25
#define MEMSET_PAE_PGTL_ALIGN
Definition: memory_clear.c:7
#define MEMSET_PAE_VMEM_ALIGN
Definition: memory_clear.c:10
static void clear_memory(void *unused)
Definition: memory_clear.c:54
static resource_t range_entry_base(const struct range_entry *r)
Definition: memrange.h:44
static resource_t range_entry_end(const struct range_entry *r)
Definition: memrange.h:50
#define memranges_each_entry(r, ranges)
Definition: memrange.h:82
static unsigned long range_entry_tag(const struct range_entry *r)
Definition: memrange.h:61
void memranges_teardown(struct memranges *ranges)
Definition: memrange.c:321
void memranges_insert(struct memranges *ranges, resource_t base, resource_t size, unsigned long tag)
Definition: memrange.c:236
static resource_t range_entry_size(const struct range_entry *r)
Definition: memrange.h:56
#define memranges_init(__ranges, __mask, __match, __tag)
Definition: memrange.h:108
#define IORESOURCE_MEM
Definition: resource.h:10
#define IORESOURCE_CACHEABLE
Definition: resource.h:19
#define IORESOURCE_STORED
Definition: resource.h:32
#define IORESOURCE_ASSIGNED
Definition: resource.h:34
u64 resource_t
Definition: resource.h:43
#define IORESOURCE_FIXED
Definition: resource.h:36
#define ENV_X86
Definition: rules.h:248
bool security_clear_dram_request(void)
To be called after DRAM init.
Definition: memory.c:13
#define NULL
Definition: stddef.h:19
unsigned long uintptr_t
Definition: stdint.h:21
Definition: memrange.h:24