「ゼロからのOS自作入門」4章 4.3〜を実行する
/
'「ゼロからのOS自作入門」4章 4.3〜を実行します(前編)'
# PixelWriterクラス(osbook_day04c)
# PixelWriterクラスの実装
mikanos/kernel/main.cppに下記の内容を追記します.
class PixelWriter{
public:
PixelWriter(const FrameBufferConfig& config) : config_{config} {
}
virtual ~PixelWriter() = default;
virtual void Write(int x, int y, const PixelColor& c) = 0;
protected:
uint8_t* PixelAt(int x, int y) {
return config_.frame_buffer + 4 * (config_.pixels_per_scan_line * y + x);
}
private:
const FrameBufferConfig& config_;
};
# PixelWriterクラスの継承
mikanos/kernel/main.cppに,PixelWriterクラスで画面に描画する内容を追記します.
class RGBResv8BitPerColorPixelWriter : public PixelWriter {
public:
using PixelWriter::PixelWriter;
virtual void Write(int x, int y, const PixelColor& c) override {
auto p = PixelAt(x, y);
p[0] = c.r;
p[1] = c.g;
p[2] = c.b;
}
};
class BGRResv8BitPerColorPixelWriter : public PixelWriter {
public:
using PixelWriter::PixelWriter;
virtual void Write(int x, int y, const PixelColor& c) override {
auto p = PixelAt(x, y);
p[0] = c.b;
p[1] = c.g;
p[2] = c.r;
}
};
# PixelWriterクラスの使い方
mikanos/kernel/main.cppに,PixelWriterクラスを使う内容を追記します.
// PixelWriterポインタの定義
char pixel_writer_buf[sizeof(RGBResv8BitPerColorPixelWriter)];
PixelWriter* pixel_writer;
// PixelWriterクラスの使い方
extern "C" void KernelMain(const FrameBufferConfig& frame_buffer_config) {
switch (frame_buffer_config.pixel_format) {
case kPixelRGBResv8BitPerColor:
pixel_writer = new(pixel_writer_buf)
RGBResv8BitPerColorPixelWriter(frame_buffer_config);
break;
case kPixelBGRResv8BitPerColor:
pixel_writer = new(pixel_writer_buf)
BGRResv8BitPerColorPixelWriter(frame_buffer_config);
break;
}
for (int x = 0; x < frame_buffer_config.horizontal_resolution; ++x){
for (int y = 0; y < frame_buffer_config.vertical_resolution; ++y){
pixel_writer->Write(x, y, {255, 255, 255});
}
}
for (int x = 0; x < 200; ++x){
for (int y = 0; y < 100; ++y){
pixel_writer->Write(x, y, {0, 255, 0});
}
}
while (1) __asm__("hlt");
}
# 配置newの演算子の定義
mikanos/kernel/main.cppに,配置newの演算子の定義を追記します.
下記の配置newは,メモリ領域の確保を実施しない.
void* operator new(size_t size, void* buf) {
return buf;
}
void operator delete(void* obj) noexcept {
}
# ビルド
下記のコードで変更したmain.cpp等を反映します.
source $HOME/osbook/devenv/buildenv.sh
cd ~/workspaces/mikanos-devcontainer/mikanos/kernel
make
cd $HOME/edk2/
source edksetup.sh
build
# Hello world
下記のコードでイメージファイルを上書きし,Hello Worldを実行します.
cd $HOME/edk2
$HOME/osbook/devenv/run_qemu.sh Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi $HOME/workspaces/mikanos-devcontainer/mikanos/kernel/kernel.elf
# ローダの改良(osbook_day04d)
今までの描画プログラムには,下記のバグが存在します.
カーネルの読み込むためのメモリ確保において,メモリの大きさを計算する処理が間違っている.
cd ~/workspaces/mikanos-devcontainer/mikanos/kernel
readelf -l kernel.elf
// Elf file type is EXEC (Executable file)
// Entry point 0x101020
// There are 5 program headers, starting at offset 64
// Program Headers:
// Type Offset VirtAddr PhysAddr
// FileSiz MemSiz Flags Align
// PHDR 0x0000000000000040 0x0000000000100040 0x0000000000100040
// 0x0000000000000118 0x0000000000000118 R 0x8
// LOAD 0x0000000000000000 0x0000000000100000 0x0000000000100000
// 0x00000000000001a8 0x00000000000001a8 R 0x1000
// LOAD 0x0000000000001000 0x0000000000101000 0x0000000000101000
// 0x00000000000001b9 0x00000000000001b9 R E 0x1000
// LOAD 0x0000000000002000 0x0000000000102000 0x0000000000102000
// 0x0000000000000000 0x0000000000000018 RW 0x1000
// GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
// 0x0000000000000000 0x0000000000000000 RW 0x0
// Section to Segment mapping:
// Segment Sections...
// 00
// 01 .rodata
// 02 .text
// 03 .bss
// 04
# 64ビット ELF のファイルヘッダの作成
mikanos/kernel/elf.hppに64ビット_ELFのファイルヘッダを追記します.
#define EI_NINDENT 16
typedef struct {
unsigned char e_indent[EI_NINDENT]:
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half shstrndx;
} Elf64_Endr;
# カーネルファイルの読み込み(Main.c)p113
# まとめ
「ゼロからのOS自作入門」4章 4.3〜を実行しました(前編).
# 参考サイト
『ゼロからのOS自作入門』をMacで動かしてみた記録(第4章 4.2 osbook_day04b) (opens new window)