본문 바로가기
프로그래밍/PC

FPC 로 OS 커널 만들기... - 2 -

by 사악신 2014. 4. 11.


오늘 포스팅은 작업 일지에 가까울 거 같습니다. 아무래도 제게 주어진 시간이 많지 않은 관계로 최대한 빨리 작업을 진행하고 있거든요. 말 그대로 닥치는대로 하고있습니다. ^^


정석대로라면 부트로더를 통해 보호 모드로 진입하고 이후, 인터럽트, 디바이스, 태스크 스위칭, 페이징 등 거의 정해진 절차처럼 커널 개발을 하게 됩니다. 수많은 OS 개발자들이 해왔던 일이고 저도 그 중 한명이 되는 겁니다. 하지만 기왕지사 조금 무리를 하며 일을 진행하는 것인만큼 뭔가 의미가 있어야하지 않을까란 생각이 들었습니다. 즉, 이 일을 해야하는 이유 혹은 가치를 정할 필요가 생겼습니다.(코딩을 하며 멀티 태스킹으로 고민했습니다. ㅋㅋ)




유산의 발굴


2년전 파스칼과 관련한 글을 포스팅한 적이 있습니다.


2012/09/07 - [프로그래밍/주저리주저리] - 파스칼(Pascal) 연서(戀書) - 1 - before 1980

2012/09/11 - [프로그래밍/주저리주저리] - 파스칼(Pascal) 연서(戀書) - 2 - after 1980, by Apple

2012/09/11 - [프로그래밍/주저리주저리] - 파스칼(Pascal) 연서(戀書) - 3 - after 1980, by Hejlsberg


"유산"에 대해 알고 싶으시다면 상기 포스팅 중 1편만 보셔도 됩니다.


현재 OS 개발은 프로젝트명 미시히(MiSiHi)로 진행하고 있습니다. 막내 딸 혹은 셋째 딸아이를 가리키는 순우리말입니다. 과거 제가 취미로 판타지 소설을 썼을 때 여주인공 이름이기도 합니다. ^^;;;;


당분간은 OS 개발을 위한 기술적 구현 검토 단계로 마구잡이식 개발이 진행될 겁니다. 그리고 자료가 구축된 후, 정해둔 컨셉에 맞춰 아키텍처를 잡아 정식 개발을 할 계획(과연...)입니다. 하지만 꼭 실현하고 싶은 기능은 어느 정도 정해져 있습니다.


  • 어플리케이션 개발환경으로 FPC 및 라자루스 지원
  • OS 에서 파스칼 RTL 기본 지원(다른 놈들은 런타임 라이브러리가 필요할 지도... 알게 뭐야.)
  • p-System 지원(마땅한 이름이 없어 그대로 썼지만 개선 후 탑재할 겁니다. OS 에 통합된 VM 이라고 보시면 됩니다.)
  • 객체지향 OS


특별히 범용 OS 로 개발할 생각은 없는 터라 최종 결과물은 아주 개성이 강한 놈이 될 수도 있습니다. 아무튼 상기 계획을 실현하기 위해서 가장 중요한 키 역할을 하는 놈은 FPC 가 됩니다. 하여, FPC 의 RTL 을 건드리는 작업을 해보았습니다.


닥치고 FPC RTL(Linux, i386)을 커널에 집어넣어 버리자.

(그외 참고: 2014/04/10 - [프로그래밍/언어 - Pascal] - FPC 2.6 지원 CPU 및 OS)





현재, GRUB 으로 부팅할 수 있게되었지만 커널은 말 그대로 깡통인 상태... resource manager 로서의 본연의 임무와 상관없이 앞으로의 목표를 위해 RTL 을 막무가내로 올려보기로 마음 먹었습니다. 후반부 작업을 미리 땡겨 간을 보는 거죠.


System 유닛을 빌드하기 위하여 디렉토리를 구성하였습니다. FPC 소스 중 rtl/linux(이하 서브디렉토리), rtl/i386, rtl/inc, rtl/unix 를 복사하였습니다.



사실, 윈도우즈랑 유사한 형태(NT 소스가 돌아 다니더라구요. ㅋㅋ)로 진행할 생각도 있었지만... 가장 빠르고 안전한 진행을 위하여 리눅스 진영의 자원을 사용하기로 마음 먹었습니다.


linux 디렉토리에 kernel.pas 를 다음과 같이 작성하고 linux 디렉토리에서 컴파일 합니다.


### delphi
unit kernel;

interface

procedure kernelmain; stdcall;

implementation

type
TVGAText = packed record
CH: Char;
Attr: Byte;
end;

TBufferScreen = array[1..25, 1..80] of TVGAText;


procedure kernelmain; stdcall; [public, alias: 'kernelmain'];
var
Screen: TBufferScreen absolute $B8000;
ScreenSave: TBufferScreen;
Buffer: array[1..80] of Byte;
x, y, i: Integer;
begin
ScreenSave := Screen;

for y := 1 to 25 do
begin
Screen[y,40].CH := ' ';
Screen[y,41].CH := ' ';
end;

for x := 40 downto 1 do
begin
for i := 1 to 25 do
begin
Move(Screen[i,2], Buffer, 78);
Move(Buffer, Screen[i,1], 78);
Move(Screen[i,41], Buffer, 78);
Move(Buffer, Screen[i,42], 78);
end;
end;
end;

end.


뭐하는 소스일까요? 후후~ 뒤에 알려드리겠습니다. 아무튼 System 의 Move 함수를 사용하고 있습니다. ^^


ppcross386 -Tlinux -b -Fi../inc -Fi../i386 -Fi../unix -Fi./i386 -FE. -di386 kernel.pas


정상적으로 컴파일하면, system.o 와 kernel.o 파일이 생성됩니다. 이것을 가지고 링킹 작업을 합니다.


ld -m elf_i386 --gc-sections -s -Tlinker.script -o kernel.bin stub.o kernel.o system.o


여기서 에러들이 주루룩 나오더군요. 하여 스타트업 코드를 참고하여 stub.asm 을 고쳐야했습니다.(이건 그냥 아무 생각없이 두들겨 넣은겁니다. 되는지 확인만 하면 되니까요.)


[bits 32]


;  header flag

MULTIBOOT_MODULE_ALIGN equ 1<<0

MULTIBOOT_MEMORY_MAP equ 1<<1

MULTIBOOT_GRAPHICS_FIELDS equ 1<<2

MULTIBOOT_ADDRESS_FIELDS equ 1<<16


; header defines

MULTIBOOT_HEADER_MAGIC equ 0x1BADB002

MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_MODULE_ALIGN | MULTIBOOT_MEMORY_MAP

MULTIBOOT_HEADER_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)


; kernel stack size

KERNEL_STACKSIZE equ 0x4000


; for fpc rtl





section .text


global _start

        global _haltproc

        global __fpc_valgrind

        global INITFINAL

        global FPC_THREADVARTABLES

        global __stkptr

        global operatingsystem_parameter_envp

        global operatingsystem_parameter_argc

        global operatingsystem_parameter_argv

extern kernelmain


; multiboot header

align 4

dd MULTIBOOT_HEADER_MAGIC

dd MULTIBOOT_HEADER_FLAGS

dd MULTIBOOT_HEADER_CHECKSUM


; entry point

_start:

mov esp, KERNEL_STACK+KERNEL_STACKSIZE ; create kernel 

push eax

push ebx

call kernelmain


_haltproc:

        cli

        hlt



section .data


__fpc_valgrind: db 0



section .data

align 8

INITFINAL:

        dw 2, 0

;        dq INIT$_SYSTEM

;        dq 0

;        dq INIT$_LNFODWRF

;        dq FINALIZE$_LNFODWRF


section .data

align 8

FPC_THREADVARTABLES:

        dw 2

;        dq THREADVARLIST_SYSTEM

;        dq THREADVARLIST_STRINGS

;        dq THREADVARLIST_EXEINFO

;        dq THREADVARLIST_LNFODWRF

;        dq THREADVARLIST_P$PROJECT1




section .bss


__stkptr: resb 4

operatingsystem_parameter_envp: resb 12

operatingsystem_parameter_argc equ operatingsystem_parameter_envp-8

operatingsystem_parameter_argv equ operatingsystem_parameter_envp-4

___fpc_threadvar_offset: resb 4




; kernel stack

;align 32

KERNEL_STACK: resb KERNEL_STACKSIZE


FPC 의 스타트업 소스들 확장자가 .S 인데요. 이게 GAS(GNU Assembler)의 소스 파일 확장자더군요. NASM(Netwide Assembler) 을 사용(간신히 검색하며 보는 정도?)하고 있던 터라 이 녀석들 구문을 살펴봤는데... 멘붕이 왔습니다. NASM 은 Intel 구문이고 GAS 는 AT&T 구문이더군요. 그러니까 어셈이긴 어셈인데 문법이 다르다는거죠.ㅋㅋㅋㅋ 생각보다 많이 다릅니다. 때려칠까 잠시 망설였지만... 구굴신께서 도와주시더군요.



왜나라 언어는 번역이 잘 되는 편이라 수월하게 귀가하는 지하철 안에서 탐독하고 오늘 오전 stub.asm 을 수정하고 적용해 보았습니다. 그리고 그 결과물...




과거 90년대 이야기(Iyagi)를 오마쥬합니다. ^^ㅋ


반응형

댓글