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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
#include "arch/kernel/main.hpp"
#include "arch/boot/pointers.hpp"
#include "arch/exception_handling/assert.hpp"
#include "arch/memory/frame_allocator.hpp"
#include "arch/memory/multiboot.hpp"
#include "arch/video/vga/text.hpp"
#include <algorithm>
namespace teachos::arch::kernel
{
auto process_memory_map(arch::memory::memory_map * mminfo, arch::memory::memory_area *& memory_areas,
uint8_t & area_count) -> void
{
auto expected_entry_size = mminfo->entry_size;
constexpr auto actual_entry_size = sizeof(arch::memory::memory_area);
arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memoryarea entry size");
auto total_size = mminfo->tag.size;
auto total_entries_size = total_size - sizeof(arch::memory::memory_map) + actual_entry_size;
auto number_of_entries = total_entries_size / actual_entry_size;
memory_areas = &mminfo->entries;
area_count = number_of_entries;
}
auto process_elf_sections(arch::memory::elf_symbols_section * symbol, uint64_t & kernel_start,
uint64_t & kernel_end) -> void
{
auto expected_entry_size = symbol->entry_size;
constexpr auto actual_entry_size = sizeof(arch::memory::elf_section_header);
arch::exception_handling::assert(expected_entry_size == actual_entry_size,
"Unexpected elf_section_header entry size");
auto expected_total_size = symbol->tag.size;
auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections;
constexpr auto actual_total_section_size = sizeof(arch::memory::elf_symbols_section) - sizeof(uint32_t);
auto actual_total_size = actual_total_entry_size + actual_total_section_size;
arch::exception_handling::assert(expected_total_size == actual_total_size, "Unexpected elf_symbols total size");
auto begin = reinterpret_cast<arch::memory::elf_section_header *>(&symbol->end);
auto end = begin + symbol->number_of_sections;
arch::exception_handling::assert(begin->is_null(), "Missing elf_section_header begin");
std::size_t symbol_table_section_count = 0U;
std::size_t dynamic_section_count = 0U;
for (auto section = begin; section != end; ++section)
{
bool const writable = section->flags.contains_flags(arch::memory::elf_section_flags::WRITABLE);
bool const occupies_memory = section->flags.contains_flags(arch::memory::elf_section_flags::OCCUPIES_MEMORY);
bool const is_executable = section->flags.contains_flags(arch::memory::elf_section_flags::EXECUTABLE_CODE);
bool const contains_duplicate_data =
section->flags.contains_flags(arch::memory::elf_section_flags::DUPLICATE_DATA);
bool const contains_strings = section->flags.contains_flags(arch::memory::elf_section_flags::CONTAINS_STRING);
bool const section_header_info_is_section_header_table_index = section->flags.contains_flags(
arch::memory::elf_section_flags::SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX);
bool const preserve_ordering_after_combination =
section->flags.contains_flags(arch::memory::elf_section_flags::PRESERVE_ORDERING_AFTER_COMBINATION);
bool const requires_special_os_processing =
section->flags.contains_flags(arch::memory::elf_section_flags::REQUIRES_SPECIAL_OS_PROCESSING);
bool const is_section_group_member =
section->flags.contains_flags(arch::memory::elf_section_flags::SECTION_GROUP_MEMBER);
bool const holds_thread_local_data =
section->flags.contains_flags(arch::memory::elf_section_flags::HOLDS_THREAD_LOCAL_DATA);
bool const is_compressed = section->flags.contains_flags(arch::memory::elf_section_flags::COMPRESSED);
bool const has_special_ordering_requirements =
section->flags.contains_flags(arch::memory::elf_section_flags::SPECIAL_ORDERING_REQUIREMENTS);
bool const is_excluded_unless_referenced_or_allocated =
section->flags.contains_flags(arch::memory::elf_section_flags::EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED);
if (writable && occupies_memory && is_executable && contains_duplicate_data && contains_strings &&
section_header_info_is_section_header_table_index && preserve_ordering_after_combination &&
requires_special_os_processing && is_section_group_member && holds_thread_local_data && is_compressed &&
has_special_ordering_requirements && is_excluded_unless_referenced_or_allocated)
{
}
switch (section->type)
{
case arch::memory::elf_section_type::PROGRAMM: {
if (section->virtual_address < kernel_start)
{
kernel_start = section->virtual_address;
}
auto virtual_address_end = section->virtual_address + section->section_size;
if (virtual_address_end > kernel_end)
{
kernel_end = virtual_address_end;
}
break;
}
case arch::memory::elf_section_type::DYNAMIC_SYMBOL_TABLE:
case arch::memory::elf_section_type::SYMBOL_TABLE:
symbol_table_section_count++;
break;
case arch::memory::elf_section_type::DYNAMIC:
dynamic_section_count++;
break;
default:
// All other cases are not important and can be ignored
break;
}
}
arch::exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value");
arch::exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value");
}
template<typename T>
requires std::is_pointer<T>::value
auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T
{
return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(ptr) + ((size + 7) & ~7));
}
auto main() -> void
{
using namespace video::vga;
text::clear();
text::cursor(false);
text::write("TeachOS is starting up...", text::common_attributes::green_on_black);
auto * multiboot_information_pointer =
reinterpret_cast<arch::memory::multi_boot_info *>(arch::boot::multiboot_information_pointer);
auto multiboot_tag = &(multiboot_information_pointer->tags);
uint64_t kernel_start = UINT64_MAX;
uint64_t kernel_end = 0;
uint64_t multiboot_start = arch::boot::multiboot_information_pointer;
uint64_t multiboot_end = multiboot_start + multiboot_information_pointer->total_size;
arch::memory::memory_area * memory_areas = nullptr;
uint8_t area_count = 0;
/*
* Loop over the multiboot2 tags to access the information needed.
* Tags are defined in the header file and are padded so that each
* Tag starts at an 8-bytes aligned adress.
*
* The increment part aligns the size to an 8-byte address.
*/
for (auto tag = multiboot_tag; tag->type != arch::memory::multi_boot_tag_type::END;
tag = align_to_8_byte_boundary(tag, tag->size))
{
switch (tag->type)
{
case arch::memory::multi_boot_tag_type::ELF_SECTIONS: {
auto symbol = reinterpret_cast<teachos::arch::memory::elf_symbols_section *>(tag);
process_elf_sections(symbol, kernel_start, kernel_end);
break;
}
case arch::memory::multi_boot_tag_type::MEMORY_MAP: {
auto mminfo = reinterpret_cast<teachos::arch::memory::memory_map *>(tag);
process_memory_map(mminfo, memory_areas, area_count);
break;
}
default:
// All other cases are not important and can be ignored
break;
}
}
auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end,
memory_areas, area_count);
auto last_allocated = allocator.allocate_frame();
auto allocated = last_allocated;
do
{
last_allocated = allocated;
allocated = allocator.allocate_frame();
} while (allocated.has_value());
video::vga::text::write("Allocated Frames", video::vga::text::common_attributes::green_on_black);
video::vga::text::write_number(allocated.value().frame_number, video::vga::text::common_attributes::green_on_black);
}
} // namespace teachos::arch::kernel
|