'제로 OS 자작입문'의 복수 파트5🍊
계속하다
설명 노트
5장까지 진행됐지만, 자신이 무엇을 하고 있는지 알아냈으니 일단 정리를 해보자.(6장에 들어가려고 했는데 어디에 무엇을 설치해야 좋을지 모르겠다.)
EDK II 부팅 로더 제작(제2장)
간단한 복습
Loader.inf Main.c MikanLoaderPkg.dec MikanLoaderPkg.dsc
Loder.inf/구성 요소 정의 파일MikanLoaderPkg.dec 패키지 선언 파일
MikanLoaderPkg.esc 패키지 설명 파일
Main.c···소스 코드
Loder.inf의 UefiMain(엔트리 포인트 기술)
→주로main() 함수에 해당한다.
이루어지다
#include <Uefi.h>
#include <Library/UefiLib.h>
EFI_STATUS EFIAPI UefiMain( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) {
Print(L"Hello, Mikan World!\n");
while(1);
return EFI_SUCCESS;
}
메모리 매핑 설치(제2장)
마땅히 담박하게 실시해야 한다
커널의 설치(3장)
간단한 내핵을 만들다.
C가 뭔데?함수가 C 언어로 정의되었음을 나타냅니다.
이름 수식의 작용을 방지하다.부작용으로서 매개 변수의 개수와 유형은 단지 다르다
같은 이름의 함수를 정의할 수 없습니다.(과부하 기능인가요)
extern "C" void KernelMain() {
while(1) __asm__("hlt");
}
가이드 측면에서 내부 핵을 호출하는 데 사용되는 실현을 실현한다.서비스 시작을 중지합니다.시작 서비스는 뒷면에서 조용히 움직여 여러 가지 처리를 하지만 방해가 된다.
//stop bootservice
EFI_STATUS status;
status = gBS->ExitBootServices(image_handle, memmap.map_key);
if(EFI_ERROR(status)){
status = GetMemoryMap(&memmap);
if(EFI_ERROR(status)) {
Print(L"failed to get memory map: %r\n", status);
while(1);
}
}
status = gBS->ExitBootServices(image_handle, memmap.map_key);
if(EFI_ERROR(status)){
Print(L"Could not exit boot service: %r\n", status);
while(1);
}
코어에서 픽셀 그리기내부 핵 측면의 전선은 아래와 같다.
reinterpret_cast는 정수 값에서 바늘 변수로 되돌아오는 것을 나타낸다
#include <cstdint>
extern "C" void KernelMain(uint64_t frame_buffer_base, uint64_t frame_buffer_size) {
uint8_t *frame_buffer = reinterpret_cast<uint8_t*>(frame_buffer_base);
for(uint64_t i = 0; i < frame_buffer_size; ++i) {
frame_buffer[i] = i % 256;
}
while(1) __asm__("hlt");
}
프레임 버퍼의 정보를 내부 핵에 전송한다.void에서 입구점을 변경한 다음 KernelMain에게 건네주기
typedef void EntryPointType(UINT64, UINT64);
EntryPointType *entry_point = (EntryPointType*)entry_addr;
entry_point(gop->Mode->FrameBufferBase, gop->Mode->FrameBufferSize);
픽셀 그리기와make 입문 (4장)
내핵으로 물건을 표시하다.
C++로 대체
가상 함수 만들기
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 클래스 만들기상속이란 한 반을 바탕으로 쓰기 기능의 차별을 두는 방법이다.
부모급부터 아이급에 덮어쓰는 경우를 오버라이드라고 한다.
class RGBResvv8bitPerColorPixelWriter : 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 BGRResvv8bitPerColorPixelWriter : 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;
}
};
지정된 pixelformat에 근거하여 두 개의 하위 클래스에 적합한 실례를 생성하다새 함수 추가
일반적인 new는 지정한 종류의 실례적인 무더기 영역을 사용합니다.
이것은 설정의 new입니다.퇴적 구역을 사용하려면 메모리 관리가 필요하지만 아직 기능이 없습니다.
따라서 설정 new를 사용합니다.새 저장 영역을 정확하게 저장하지 못하게 설정합니다.
정렬 기능을 사용합니다.
사실 delete는 필요하지 않지만 delete가 없으면 컴파일 오류가 됩니다.
void* operator new(size_t size, void* buf) {
return buf;
}
void operator delete(void* obj) noexcept {
}
개량 적재기
메모리 읽기 메모리를 확보하는 부분에서 메모리 크기를 계산하는 처리가 잘못되었습니다.
페이지 단위 읽기에서 바이트 단위 읽기로 변경
임시 영역에 커널 파일만 불러오고 싶습니다.
status = gBS->AllocatePool(EfiLoaderData, kernel_file_size, &kernel_buffer);
if(EFI_ERROR(status)) {
Print(L"failed to allocate pool: %r", status);
Holt();
}
kernel_file->Read(kernel_file, &kernel_file_size, kernel_buffer);
if(EFI_ERROR(status)) {
Print(L"error: %r", status);
Holt();
}
글씨를 쓰다(제5장)
글꼴 데이터 만들기
처음 0b는 이진수를 나타낸다
const uint8_t kFontA[16] = {
0b00000000,
0b00011000,
0b00011000,
0b00011000,
0b00011000,
0b00100100,
0b00100100,
0b00100100,
0b00100100,
0b01111110,
0b01000010,
0b01000010,
0b01000010,
0b11100111,
0b00000000,
0b00000000,
};
이 글꼴 데이터를 사용하여 문자를 씁니다.비트 연산을 사용하여 충전 여부를 결정하다.
void WriteAscii(PixelWriter& writer, int x, int y, char c, const PixelColor& color) {
if(c != 'A') {
return;
}
for(int dy = 0; dy < 16; ++dy) {
for(int dx = 0; dx < 8; ++dx) {
if((kFontA[dy] << dx) & 0x80u) {
writer.Write(x + dx, y + dy, color);
}
}
}
}
※ 80u의 u는 unsigned를 나타냅니다.비트 연산자: &는 AND 연산자를 나타냅니다.
따라서 다음과 같이 계산한다.
예) 0b11000001(0xC1)의 경우
kFontA[dy] << dx
0b11000001<0위는 왼쪽으로 이동하지만 변화가 없습니다.
0xC1 & 0x80 → 0x80 (바르기)
분할 컴파일
보시면 아실 거예요.
글꼴 추가
hanakaku.txt를 받았습니다. 다음과 같습니다.
../tool/makefont.py -o hankaku.bin hankaku.txt
objcopy -I binary -O elf64-x86-64 -B i386:x86-64 hanakaku.bin hanbaku.o
hankaku.o 데이터를 변수 참조로 사용참조할 경우 extern을 사용합니다.이것은 다른 대상 파일을 인용하는 변수를 가리킨다.
extern const uint8_t _binary_hankaku_bin_start;
extern const uint8_t _binary_hankaku_bin_end;
extern const uint8_t _binary_hankaku_bin_size;
문자열 그리기
뭐, 여기를 보면 알겠지
콘솔 클래스 구현
콘솔은 콘솔을 의미합니다.
static OS에서 스토리지로 로드 완료 때까지 대기
static const int kRows = 25, kColumns = 80;
console 클래스 생성 실례Console console{*pixel_writer, {0, 0, 0}, {0, 255, 0}};
printk의 실현
Linux에는 내장 내부에서 메시지를 보내는 데 사용되는 printk () 함수가 있습니다.
이 함수는 내부 핵 내의 어느 곳에서든 사용할 수 있다.나는 그것을 실시할 것이다.
printk의 실현 중...(3점)은 가변 길이 매개변수입니다.
va_리스트로 받습니다.
int printk(const char* format, ...) {
va_list ap;
int result;
char s[1024];
va_start(ap, format);
result = vsprintf(s, format, ap);
va_end(ap);
console->PutString(s);
return result;
}
Reference
이 문제에 관하여('제로 OS 자작입문'의 복수 파트5🍊), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/omiso/articles/5f58cc80748ad0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)