summaryrefslogtreecommitdiffhomepage
path: root/src/loader/memory.c
blob: a38e48bd5056410d9be0b7cdc319f3a730c05e6a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// MIT License, Copyright (c) 2021 Marvin Borner
// Memory map generator

#include <log.h>
#include <memory.h>
#include <panic.h>
#include <real.h>

/**
 * Memory map using e820 BIOS call
 */

#define E820_MAX_ENTRIES 256 // Spec

enum e820_entry_type {
	E820_MEMORY_NONE,
	E820_MEMORY_USABLE,
	E820_MEMORY_RESERVED,
	E820_MEMORY_RECLAIMABLE,
	E820_MEMORY_ACPI_NVS,
	E820_MEMORY_UNUSABLE,
};

struct e820_entry {
	u32 base_low;
	u32 base_high;
	u32 length_low;
	u32 length_high;
	enum e820_entry_type type;
	u32 unused;
} PACKED;

u16 e820_count = 0;
struct e820_entry e820_map[E820_MAX_ENTRIES] = { 0 };

static u8 memory_e820(void)
{
	struct real_regs r = { 0 };

	for (u32 i = 0; i < E820_MAX_ENTRIES; i++) {
		struct e820_entry entry = { 0 };

		r.eax = 0xe820;
		r.ecx = 24;
		r.edx = 0x534d4150;
		r.edi = (u32)&entry;
		real_int(0x15, &r, &r);

		if (r.eflags & EFLAGS_CF) {
			e820_count = i;
			return 1;
		}

		e820_map[i] = entry;

		if (!r.ebx) {
			e820_count = i++;
			return 1;
		}
	}

	return 0;
}

/**
 * Configure memory map
 */

#define MAP_MAX_ENTRIES 256

static struct memory_entry mem[MAP_MAX_ENTRIES] = { 0 };
static struct memory_map map = { .entry = mem, .count = 0 };

static void memory_map_e820(void)
{
	u32 i;
	for (i = 0; i < COUNT(e820_map); i++) {
		struct e820_entry *e820_entry = &e820_map[i];
		struct memory_entry *map_entry = &mem[i];

		map_entry->base = e820_entry->base_low;
		map_entry->length = e820_entry->length_low;

		// Set type accordingly
		switch (e820_entry->type) {
		case E820_MEMORY_NONE:
			map_entry->type = MEMORY_USABLE;
			continue;
		case E820_MEMORY_USABLE:
			map_entry->type = MEMORY_USABLE;
			break;
		case E820_MEMORY_RESERVED:
			map_entry->type = MEMORY_RESERVED;
			break;
		case E820_MEMORY_RECLAIMABLE:
			map_entry->type = MEMORY_RECLAIMABLE;
			break;
		case E820_MEMORY_ACPI_NVS:
			map_entry->type = MEMORY_ACPI_NVS;
			break;
		case E820_MEMORY_UNUSABLE:
			map_entry->type = MEMORY_UNUSABLE;
			break;
		default:
			panic("Unknown e820 type\n");
		}
	}

	map.count = i;
}

struct memory_map *memory_map_get(void)
{
	return &map;
}

void memory_map(void)
{
	if (memory_e820()) {
		memory_map_e820();
		return;
	}

	panic("Couldn't find memory map\n");
}