2020301918-os/boot/loadkernel.c
2022-10-02 12:54:35 +08:00

164 lines
3.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 类型
*/
typedef int i32;
typedef unsigned int u32;
typedef short i16;
typedef unsigned short u16;
typedef char i8;
typedef unsigned char u8;
// 通常描述一个对象的大小,会根据机器的型号变化类型
typedef u32 size_t;
// elf文件格式会用
typedef u32 Elf32_Addr;
typedef u16 Elf32_Half;
typedef u32 Elf32_Off;
typedef i32 Elf32_Sword;
typedef u32 Elf32_Word;
/*
* elf相关
*/
#define KERNEL_ELF 0x80400
#define EI_NIDENT 16
typedef struct elf32_hdr {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
typedef struct elf32_phdr {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
/*
* 显示相关
*/
#define TERMINAL_COLUMN 80
#define TERMINAL_ROW 25
#define TERMINAL_POS(row, column) ((u16)(row) * TERMINAL_COLUMN + (column))
/*
* 终端默认色,黑底白字
*/
#define DEFAULT_COLOR 0x0f00
/*
* 这个函数将content数据2字节写到终端第disp_pos个字符
* 第0个字符在0行0列第1个字符在0行1列第80个字符在1行0列以此类推
* 用的是内联汇编等价于mov word [gs:disp_pos * 2], content
*/
inline static void
write_to_terminal(u16 disp_pos, u16 content)
{
asm(
"mov %1, %%gs:(%0)" ::"r"(disp_pos * 2), "r"(content)
: "memory");
}
/*
* 清屏
*/
static void
clear_screen()
{
for (int i = 0; i < TERMINAL_ROW; i++)
for (int j = 0; j < TERMINAL_COLUMN; j++)
write_to_terminal(TERMINAL_POS(i, j),
DEFAULT_COLOR | ' ');
}
static void *
memset(void *v, int c, size_t n)
{
char *p;
int m;
p = v;
m = n;
while (--m >= 0)
*p++ = c;
return v;
}
static void *
memcpy(void *dst, const void *src, size_t n)
{
const char *s;
char *d;
s = src;
d = dst;
if (s < d && s + n > d) {
s += n;
d += n;
while (n-- > 0)
*--d = *--s;
} else {
while (n-- > 0)
*d++ = *s++;
}
return dst;
}
/*
* 初始化函数加载kernel.bin的elf文件并跳过去。
*/
void
load_kernel()
{
clear_screen();
for (char *s = "----start loading kernel elf----", *st = s; *s; s++)
write_to_terminal(s - st, DEFAULT_COLOR | *s);
Elf32_Ehdr *kernel_ehdr = (Elf32_Ehdr *)KERNEL_ELF;
Elf32_Phdr *kernel_phdr = (void *)kernel_ehdr + kernel_ehdr->e_phoff;
for (u32 i = 0; i < kernel_ehdr->e_phnum; i++, kernel_phdr++)
{
if (kernel_phdr->p_type != PT_LOAD)
continue;
// 将elf的文件数据复制到指定位置
memcpy(
(void *)kernel_phdr->p_vaddr,
(void *)kernel_ehdr + kernel_phdr->p_offset,
kernel_phdr->p_filesz);
// 将后面的字节清零(p_memsz >= p_filesz)
memset(
(void *)kernel_phdr->p_vaddr + kernel_phdr->p_filesz,
0,
kernel_phdr->p_memsz - kernel_phdr->p_filesz);
}
((void (*)(void))(kernel_ehdr->e_entry))();
}