-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloader.cpp
More file actions
136 lines (106 loc) · 4.64 KB
/
loader.cpp
File metadata and controls
136 lines (106 loc) · 4.64 KB
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
#include <elf/image.h>
#include <hal/mem.h>
#include <handover/builder.h>
#include <kapalaframe-base/align.h>
#include <kapalaframe-base/size.h>
#include <kapalaframe-logger/logger.h>
#include <kapalaframe-sys/chan.h>
#include <kapalaframe-sys/file.h>
#include <kapalaframe-sys/mmap.h>
#include "fw.h"
#include "loader.h"
namespace ShoolLoader {
void enterKernel(usize entry, usize payload, usize stack, usize vmm);
Res<> loadEntry(Entry const& entry) {
logInfo("opstart: preparing payload...");
auto payloadMem = try$(Sys::mmap().read().size(kib(16)).mapMut());
logInfo("opstart: payload at vaddr: {p} paddr: {p}", payloadMem.vaddr(), payloadMem.paddr());
Handover::Builder payload{payloadMem.mutBytes()};
payload.agent("opstart");
payload.add(Handover::SELF, 0, payloadMem.prange());
logInfo("opstart: loading kernel file...");
auto kernelFile = try$(Sys::File::open(entry.kernel.url));
auto kernelMem = try$(Sys::mmap().map(kernelFile));
Elf::Image image{kernelMem.bytes()};
payload.add(Handover::FILE, 0, kernelMem.prange());
logInfo("opstart: kernel at vaddr: {p} paddr: {p}", kernelMem.vaddr(), kernelMem.paddr());
if (not image.valid()) {
logError("opstart: invalid kernel image");
return Error::invalidData("invalid kernel image");
}
logInfo("opstart: setting up stack...");
auto stackMap = try$(Sys::mmap().stack().size(Hal::PAGE_SIZE * 16).mapMut());
payload.add(Handover::STACK, 0, stackMap.prange());
logInfo("opstart: stack at vaddr: {p} paddr: {p}", stackMap.vaddr(), stackMap.paddr());
logInfo("opstart: loading kernel image...");
for (auto prog : image.programs()) {
if (prog.type() != Elf::Program::LOAD) {
continue;
}
usize paddr = prog.vaddr() - Handover::KERNEL_BASE;
usize memsz = Hal::pageAlignUp(prog.memsz());
logInfo("opstart: loading segment: paddr={p}, vaddr={p}, memsz={p}, filesz={p}", paddr, prog.vaddr(), memsz, prog.filez());
usize remaining = prog.memsz() - prog.filez();
memcpy((void*)paddr, prog.buf(), prog.filez());
memset((void*)(paddr + prog.filez()), 0, remaining);
payload.add(Handover::KERNEL, 0, {paddr, memsz});
}
logInfo("opstart: loading additional blobs...");
for (auto const& blob : entry.blobs) {
logInfo("opstart: loading blob: {}", blob.url);
auto blobFile = try$(Sys::File::open(blob.url));
auto blobMem = try$(Sys::mmap().map(blobFile));
auto blobRange = blobMem.prange();
auto propStr = try$(Json::unparse(blob.props));
payload.add({
.tag = Handover::FILE,
.start = blobRange.start,
.size = blobRange.size,
.file = {
.name = (u32)payload.add(blob.url.str()),
.meta = (u32)payload.add(propStr),
},
});
// NOTE: We leak the blob memory here because we don't want to
// want raii to unmap the blob before we enter the kernel.
blobMem.leak();
}
logInfo("opstart: handling kernel requests...");
auto maybeSection = image.sectionByName(Handover::REQUEST_SECTION);
if (not maybeSection) {
logError("opstart: missing .handover section");
return Error::invalidData("missing .handover section");
}
auto requests = try$(maybeSection).slice<Handover::Request>();
for (auto const& request : requests) {
logInfo(" - {}", request.name());
}
auto vmm = try$(Fw::createVmm());
logInfo("opstart: mapping kernel...");
try$(vmm->mapRange(
{Handover::KERNEL_BASE + Hal::PAGE_SIZE, gib(2) - Hal::PAGE_SIZE - Hal::PAGE_SIZE},
{Hal::PAGE_SIZE, gib(2) - Hal::PAGE_SIZE - Hal::PAGE_SIZE},
Hal::Vmm::READ | Hal::Vmm::WRITE
));
logInfo("opstart: mapping upper half...");
try$(vmm->mapRange(
{Handover::UPPER_HALF + Hal::PAGE_SIZE, gib(4) - Hal::PAGE_SIZE},
{Hal::PAGE_SIZE, gib(4) - Hal::PAGE_SIZE},
Hal::Vmm::READ | Hal::Vmm::WRITE
));
logInfo("opstart: mapping boot-agent image...");
auto loaderImage = Fw::imageRange();
try$(vmm->mapRange(
Hal::identityMapped(loaderImage),
loaderImage,
Hal::Vmm::READ | Hal::Vmm::WRITE
));
logInfo("opstart: finalizing and entering kernel, see you on the other side...");
usize ip = image.header().entry;
usize sp = Handover::KERNEL_BASE + (usize)stackMap.mutBytes().end();
logInfo("opstart: ip:{x} sp:{x} payload:{}", ip, sp, (usize)&payload.finalize());
try$(Fw::finalizeHandover(payload));
Fw::enterKernel(ip, payload.finalize(), sp, *vmm);
unreachable();
}
} // namespace ShoolLoader