# os develop ch2 https://littleosbook.github.io/ https://chunyeung.medium.com/%E8%87%AA%E5%88%B6%E4%B8%80%E5%80%8B-linux-%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1-1-1cc4e60ea7f7 ## 2.1 Tools #### 開發環境: ubuntu(wsl) 使用`cat /etc/lsb-release`查看版本 ``` $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=20.04 DISTRIB_CODENAME=focal DISTRIB_DESCRIPTION="Ubuntu 20.04.4 LTS" ``` ref:https://shengyu7697.github.io/ubuntu-version/ 使用`sudo apt-get install build-essential nasm genisoimage bochs bochs-sdl`安裝需要的工具 ### 程式語言:C 書中提到使用C以及GCC做編譯,對此書中解釋,生成作業系統需要非常精確的程式碼生成,以及對記憶體的直接操作,其他程式語言若也有相似的性質也可以做為開發OS用。 ### complier:gcc #### `__attribute__` 在此會使用到gcc的extension`__attribute__((packed))`因此書中建議只使用gcc來做開發,這個用途主要是用來告訴編譯器,讓struct中的結構照著原本的宣告的排列,而不做最佳化 ### assembler:NASM 書中解釋因為比較偏好NASM的語法而不是GNU的 ### host computer 前面提過,我的開發環境為ubuntu 20.04 ### build:Make ### target computer(VM) 這邊指的是編譯完成之後,os要跑的機器,書中推薦使用虛擬機來跑,因為這會比實體機來的快而且方便多了,這邊使用前面安裝的Bochs,這是一個x86 (IA-32)指令集的emulator,會推薦使用這個的原因是因為他有完整的debeg功能,此外書中還介紹QEMU還有VirtualBox #### Bochs #### QEMU #### VirtualBox ## 2.2 booting 開機的過程牽涉到一連串小程式的控制權轉移,每個階段的程式都會比前一階段強大一些,而os就是最後一個程式,以下為書本中的簡單開機過程: ```mermaid graph LR; BIOS-->GRUB1-->GRUB2-->OS ``` ### 2.2.1 BIOS BIOS(Basic Input Output System),是開機後第一個執行的程式,這隻程式通常以唯讀記憶體的模式存在電腦主機板中,主要功能為執行一些用來顯示螢幕、讀取鍵盤輸入等等功能,而現在的OS不使用BIOS來與其他裝置溝通,而是透過driver直接存取硬體,目前的BIOS大多用來執行一些開機自我診斷(檢測記憶體、硬碟是否正常...)然後將控制權轉交給bootloader ### 2.2.2 Bootloader bootloader的主要任務是將控制權轉移給我們以及OS的撰寫者,然而因為一些硬體限制以及向下相容的考量,bootloader被拆分成兩個部分,第一個部分將控制權轉移給第二個部分最後再轉交給OS。 撰寫一個bootloader需要使用很多low-level的程式碼與BIOS作互動,因此書中解釋道,這邊僅使用現成已存在的bootloader GNU GRand Unified Bootloader(GRUB)。 使用GRUB,OS可以使用ELF格式的執行檔,GRUB可將這個類型的執行檔載入記憶體中,在kernel的編譯中,要求以特定的布局方式存在記憶體中。 #### ELF ### 2.2.3 the operation system GRUB轉換控制權給OS的方式為跳(jumped)到特定記憶體位置,GRUB是根據一個特定的數字(magic number)來得知要跳到哪個位置,這個特定的數字必須保證每次的jumped都會跳到OS而不是一個隨機的程式碼,這個特定的數字為GRUB多重開機規範的一部分(multiboot specification),而當jumped完成之後OS就開始控制整台PC #### jumped 這部分是否對應組合語言中的program counter的jumped還需要再查相關資料 #### multiboot specification --- ## Hello Cafebabe 這個章節的重點為描述一個可以與GRUB一起使用的最小OS,功能僅為將`0xCAFEBABE`寫入`exa`暫存器(register) - exa register ### Compiling the Operating System 這個最簡易的OS僅使用組合語言(assembly)寫成命名為`loader.s`: ``` global loader ; the entry symbol for ELF MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant FLAGS equ 0x0 ; multiboot flags CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum ; (magic number + checksum + flags should equal 0) section .text: ; start of the text (code) section align 4 ; the code must be 4 byte aligned dd MAGIC_NUMBER ; write the magic number to the machine code, dd FLAGS ; the flags, dd CHECKSUM ; and the checksum loader: ; the loader label (defined as entry point in linker script) mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax .loop: jmp .loop ; loop forever ``` 這個小小型os只做一件事情:將一個特定的數字`0xCAFEBABE`寫入`exa`暫存器,這個`0xCAFEBABE`基本上不太可能會在作業系統沒有設定值的情況下出現在`exa`暫存器中。 接下來我們可以將這個`loader.s`編譯成32 bit的ELF物件。 指令如下: ```bash nasm -f elf32 loader.s ``` 出現結果如下: ```bash $ls loader.s loader.o ``` ### 2.3.2 linking the kernel 產生了物件之後,接著必須透過link來產生可執行檔,這個過程必須比平常的程式多一些特別的作法,首先我們希望GRUB載入kernel在大於`0x00100000`的位置(約為1MB),因為在低於1MB的位置會被GRUB、BIOS、memory-mapped I/O所使用,因此,我們需要如下的script GNU LD: ``` ENTRY(loader) /* the name of the entry label */ SECTIONS { . = 0x00100000; /* the code should be loaded at 1 MB */ .text ALIGN (0x1000) : /* align at 4 KB */ { *(.text) /* all text sections from all files */ } .rodata ALIGN (0x1000) : /* align at 4 KB */ { *(.rodata*) /* all read-only data sections from all files */ } .data ALIGN (0x1000) : /* align at 4 KB */ { *(.data) /* all data sections from all files */ } .bss ALIGN (0x1000) : /* align at 4 KB */ { *(COMMON) /* all COMMON sections from all files */ *(.bss) /* all bss sections from all files */ } } ``` 將這個檔案存為`link.ld`然後執行以下指令: ``` ld -T link.ld -melf_i386 loader.o -o kernel.elf ``` 將會得到`kernel.elf`檔 ### 2.3.2 obtaining GRUB 由於我們目前的OS的ISO檔可以被GRUB還有GRUB2所使用,此外由於要使用`stage2_eltorito`bootloader這個GRUB0.97所建立的檔案,書中也解釋這個版本的`configure`並沒有非常好的執行在ubuntu上,因此書中提供另一個修改過的`stage2_eltorito`只要將這個檔案與前面產生出來的`loader.s` `link.ld`檔案放在一起執行就可以了,然而書中提供的連結無法下載 從網路上找到有高手放了一份在github上: https://thusharasamaweera.medium.com/ymeos-lets-build-an-os-c4485135147 ### 2.3.4 Building an ISO Image 可執行檔(executable)需要放置在VM或是實體機可以載入的媒體中(media)本書使用ISO檔,書中解釋,其他媒體(floppy images...)也可以取決於要執行的虛擬機或是實體機支援哪些格式。 所以接下來要建立一個kernel的ISO,這裡使用`genisoimage`指令,必須先依照指定個格式來建立資料夾,以下為書中的指令: ```bash mkdir -p iso/boot/grub # create the folder structure cp stage2_eltorito iso/boot/grub/ # copy the bootloader cp kernel.elf iso/boot/ # copy the kernel ``` 在此,須先建立GRUB的設定檔`menu.lst`這個檔案可以設定GRUB的一些option內容如下: ``` default=0 timeout=0 title os kernel /boot/kernel.elf ``` 在此須將`menu.lst`放置在`iso/boot/grub`下因此資料夾的結構如下: ``` iso |-- boot |-- grub | |-- menu.lst | |-- stage2_eltorito |-- kernel.elf ``` 然後下以下指令建立image: ``` genisoimage -R \ -b boot/grub/stage2_eltorito \ -no-emul-boot \ -boot-load-size 4 \ -A os \ -input-charset utf8 \ -quiet \ -boot-info-table \ -o os.iso \ iso ``` 選項相關的細節需參考`genisoimage`的相關文件,在經過這個指令之後將會產生`os.iso`檔 ### 2.3.5 Running Bochs 接下來要將產生出來的`os.iso`檔放在`Bochs`上跑在此需要設定一些Bochs的一些選項內容如下: ``` megs: 32 display_library: sdl romimage: file=/usr/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest ata0-master: type=cdrom, path=os.iso, status=inserted boot: cdrom log: bochslog.txt clock: sync=realtime, time0=local cpu: count=1, ips=1000000 ``` 其中`romimage`還有`vgaromimage`的路經需要調整為自己電腦中的路徑 將以上內容存為`bochsrc.txt` 然後用以下指令: ``` bochs -f bochsrc.txt -q ``` 其中`-f`用來指令config file -q用來略過start menu,書中寫道,執行完之後應該可以看到`bochslog.txt`可以從中找到cpu的模擬器然後找到`RAX=00000000CAFEBABE or EAX=CAFEBABE`如果有發現這個訊息表示有成功執行起OS。 在 https://chunyeung.medium.com/%E8%87%AA%E5%88%B6%E4%B8%80%E5%80%8B-linux-%E4%BD%9C%E6%A5%AD%E7%B3%BB%E7%B5%B1-3-run-os-run-c3f9232532c6 有提到若使用無GUI的ubuntu來執行,會出現無法正常顯示的問題,筆者現在就碰到這個問題。 在有GUI界面的ubuntu時出現: ``` dlopen failed for module 'x' (libbx_x.so): file not found ``` 根據這篇文章: https://www.cnblogs.com/sea-stream/p/10096749.html 安裝bochs-x就解決了 ``` sudo apt-get install bochs-x ``` 若出現: `display library 'sdl' not available` 根據這篇文章將std1改為std2 https://stackoverflow.com/questions/63159511/bochs-display-library-sdl-not-available ###### tags: `OS`