coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ramdetect.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <types.h>
4 #include <symbols.h>
5 #include <device/mmio.h>
6 #include <ramdetect.h>
7 #include <console/console.h>
8 
9 #define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e))
10 
11 int __weak probe_mb(const uintptr_t dram_start, const uintptr_t size)
12 {
13  uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
14  static const uint32_t patterns[] = {
15  0x55aa55aa,
16  0x12345678
17  };
18  void *ptr = (void *) addr;
19  size_t i;
20 
21  /* Don't accidentally clober oneself. */
22  if (OVERLAP(addr, addr + sizeof(uint32_t), (uintptr_t)_program, (uintptr_t) _eprogram))
23  return 1;
24 
25  uint32_t old = read32(ptr);
26  for (i = 0; i < ARRAY_SIZE(patterns); i++) {
27  write32(ptr, patterns[i]);
28  if (read32(ptr) != patterns[i])
29  break;
30  }
31 
32  write32(ptr, old);
33  return i == ARRAY_SIZE(patterns);
34 }
35 
36 /* - 20 as probe_size is in MiB, - 1 as i is signed */
37 #define MAX_ADDRESSABLE_SPACE (sizeof(size_t) * 8 - 20 - 1)
38 
39 /* Probe an area if it's read/writable. */
40 size_t probe_ramsize(const uintptr_t dram_start, const size_t probe_size)
41 {
42  ssize_t i;
43  size_t msb = 0;
44  size_t discovered = 0;
45 
46  static size_t saved_result;
47  if (saved_result)
48  return saved_result;
49 
50  /* Find the MSB + 1. */
51  size_t tmp = probe_size;
52  do {
53  msb++;
54  } while (tmp >>= 1);
55 
56  /* Limit search to accessible address space */
57  msb = MIN(msb, MAX_ADDRESSABLE_SPACE);
58 
59  /* Compact binary search. */
60  for (i = msb; i >= 0; i--)
61  if (probe_mb(dram_start, (discovered | (1ULL << i))))
62  discovered |= (1ULL << i);
63 
64  saved_result = discovered;
65  printk(BIOS_DEBUG, "RAMDETECT: Found %zu MiB RAM\n", discovered);
66  return discovered;
67 }
int probe_mb(const uintptr_t dram_start, const uintptr_t size)
Definition: ramdetect.c:27
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define MIN(a, b)
Definition: helpers.h:37
#define MiB
Definition: helpers.h:76
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
size_t probe_ramsize(const uintptr_t dram_start, const size_t probe_size)
Definition: ramdetect.c:40
#define OVERLAP(a, b, s, e)
Definition: ramdetect.c:9
#define MAX_ADDRESSABLE_SPACE
Definition: ramdetect.c:37
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
__SIZE_TYPE__ ssize_t
Definition: stddef.h:13
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21