-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLoad.c
214 lines (203 loc) · 5.8 KB
/
Load.c
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include <Load.h>
#include <Library/MemoryAllocationLib.h>
EFI_STATUS LoadFile(
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *file, CHAR16 *filename, ADDRESS *addr)
{
EFI_FILE_PROTOCOL *target = NULL;
EFI_STATUS status = OpenFile(
file, filename, &target, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (RETRURN_IF_ERROR(status, L"read"))
{
return status;
}
UINT64 infoBuffer = sizeof(EFI_FILE_INFO) + 128;
EFI_FILE_INFO *fileInfo = GetFileInfo(target, &infoBuffer);
UINT64 fileSize = fileInfo->FileSize;
status = FreeM((VOID *)fileInfo);
if (RETRURN_IF_ERROR(status, L"Free memory by file info"))
{
return status;
}
status = ReadToMemoryPage(target, &fileSize, addr);
return CHECK_ERROR_BEFORELOG(status, L"load elf");
}
EFI_STATUS LoadElf(
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *file, CHAR16 *filename, ADDRESS *addr)
{
EFI_STATUS status = LoadFile(file, filename, addr);
return CHECK_ERROR_BEFORELOG(status, L"load elf");
}
BmpStruct LoadBmpFileToMemory(
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *file,
CHAR16 *filename)
{
BmpStruct bmp;
EFI_FILE_PROTOCOL *target = NULL;
ADDRESS addr;
EFI_STATUS status = OpenFile(
file, filename, &target, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (RETRURN_IF_ERROR(status, L"read logo"))
{
return bmp;
}
UINT64 infoBuffer = 1000;
EFI_FILE_INFO *fileInfo = GetFileInfo(target, &infoBuffer);
UINT64 fileSize = fileInfo->FileSize;
status = ReadToMemoryPage(target, &fileSize, &addr);
if (RETRURN_IF_ERROR(status, L"Read memory by logo"))
{
return bmp;
}
//读取宽高
bmp = ParseBmpHeader(addr);
bmp.size = fileSize;
// 对角翻转
status = ReserveMemory(&addr, bmp.size, bmp.width, bmp.height, bmp.offset);
if (RETRURN_IF_ERROR(status, L"Reserve memory by logo"))
{
return bmp;
}
//剧中显示
bmp.start = addr + bmp.offset;
status = FreeM((void *)fileInfo);
if (RETRURN_IF_ERROR(status, L"Free memory by logo-bmpstruct"))
{
return bmp;
}
//设置开始地址
#ifdef LOG
Print(L"read start:%d\n", bmp.start);
#endif //LOG
//打印
return bmp;
}
EFI_STATUS ByeBootServices(
IN EFI_HANDLE ImageHandle)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap=NULL;
UINTN MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
Status = gBS->GetMemoryMap(
&MemoryMapSize,
MemoryMap,
&MapKey,
&DescriptorSize,
&DescriptorVersion);
Status = AllocateM(MemoryMapSize,(VOID **)&MemoryMap);
if (RETRURN_IF_ERROR(Status, L"Allocate Boot!"))
{
return Status;
}
FreeM((VOID *)MemoryMap);
Status = gBS->GetMemoryMap(
&MemoryMapSize,
MemoryMap,
&MapKey,
&DescriptorSize,
&DescriptorVersion);
if (RETRURN_IF_ERROR(Status, L"Exit Boot!"))
{
Print(L"Continue ...\n");
}
Status = gBS->ExitBootServices(
ImageHandle, MapKey);
// 退出后内存地址变化了
return Status;
}
/**
* @brief
* 将加载的段放入指定位置
* @param elf
* @return EFI_STATUS
*/
EFI_STATUS copyElfToEntry(Elf64_Ehdr *elf, ADDRESS start)
{
// 遍历所有段
EFI_STATUS status = EFI_SUCCESS;
ADDRESS PHeader;
Elf64_Phdr *Phdr;
UINT8 Index;
ADDRESS MemStart = 0;
UINTN size = elf->e_phentsize * elf->e_phnum + elf->e_entry;
status = AllocatePage(calPage(size), &MemStart);
if (RETRURN_IF_ERROR(status, L"allocate Page Header"))
{
return status;
}
PHeader = start + elf->e_phoff;
for (Index = 0; Index < elf->e_phnum; Index++)
{
Phdr = (Elf64_Phdr *)PHeader;
if (Phdr->p_type == PT_LOAD)
{
VOID *VirMemStart;
VOID *SegmentStart;
VOID *ExtraZeroes;
UINTN ExtraZeroesCount;
#ifdef LOG
Print(L"Load:PT_LOAD [%d]\n", Index);
#endif //LOG
/* code */
VirMemStart = (VOID *)(MemStart + Phdr->p_vaddr);
SegmentStart = (VOID *)(start + Phdr->p_paddr);
// load
gBS->CopyMem(VirMemStart, SegmentStart, Phdr->p_filesz);
// 缺少中间段段填充
ExtraZeroes = (VOID *)((ADDRESS)VirMemStart + Phdr->p_filesz);
ExtraZeroesCount = Phdr->p_memsz - Phdr->p_filesz;
if (ExtraZeroesCount > 0)
{
Print(L"extend zero \n");
gBS->SetMem(ExtraZeroes, 0x00, ExtraZeroesCount);
}
}
PHeader += elf->e_phentsize;
}
elf->e_entry += MemStart;
for (UINTN i = 0; i < 0x50; i++)
{
UINT8 *data;
data = (UINT8 *)(elf->e_entry + i);
Print(L"%X|", *data);
}
Print(L"\n");
return status;
}
//加载ELF
EFI_STATUS LoadElf64ToMemroy(EFI_HANDLE ImageHandle, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *file, CHAR16 *filename, ADDRESS *load, Elf64_Ehdr *elf)
{
// 分析和载入
#ifdef LOG
Print(L"log:addr:%d\n", *load);
#endif //LOG
EFI_STATUS status = LoadFile(file, filename, load);
#ifdef LOG
Print(L"log:addr:%d\n", *load);
#endif //LOG
//解析ELF格式
if (RETRURN_IF_ERROR(status, L"load elf"))
{
return status;
}
*elf = *((Elf64_Ehdr *)*load);
#ifdef LOG
Print(L"read entry point:%X,type:%X,flag:%X\n", elf->e_entry, elf->e_type, elf->e_flags);
#endif
// 拷贝内存
UINT8 IdentMagic[4] = {0x7f, 0x45, 0x4c, 0x46};
int i = 0;
for (i = 0; i < 4; i++)
{
if (elf->e_ident[i] != IdentMagic[i])
{
return EFI_INVALID_PARAMETER;
}
}
status = copyElfToEntry(elf, *load);
return CHECK_ERROR_BEFORELOG(status, L"Copy ELF segment");
}