0から作るソフトウェア開発
日々勉強中。。。 |
Follow @Nina_Petipa |
0から作るOS開発 Grubその3 GRUBから起動できる自作OSを作成する |
マルチブートヘッダー | |||
---|---|---|---|
マジックフィールド | |||
オフセット | 型式 | フィールド名 | 説明 |
0 | u32 | magic | マルチブートヘッダーを特定するためのマジックナンバーです。 マジックナンバーとして”必ず0x1BADB002を設定します”。 |
4 | u32 | flags |
このフィールドにはOSが必要な機能とブートローダーが必要な情報を
ヘッダーに格納しているかどうかを示すフラグです。
ビット0:1に設定している場合には、GRUBは、 OSと一緒にロードするモジュールをページ境界(4KB境界)に配置します。 (OSのなかには起動時に用意しているページに、 モジュールがロードされることを前提としているものがあるためです。) ビット1:1に設定している場合には、GRUBは OSに引数として渡す ブート情報構造体 のmem_*フィールドに、システムで利用可能なメモリー情報を セットします。 ビット2:1に設定している場合、OSは ブート情報構造体 のビデオモードテーブルを使用しますので、GRUBは テーブル値をセットする必要があります。 ビット16:1に設定している場合には、 マルチブートヘッダーのオフセット12から28が有効となります。 セットされている場合、GRUBは ELFフォーマット以外の実行形式のカーネルをロードすることができます。 |
8 | u32 | checksum |
チェックサムを設定します。
magicフィールドの値とflagsフィールドの値の合計と
checksumフィールドの値を足すと0になるような32ビットのチェックサムの値を設定する
必要があります。
|
アドレスフィールド | |||
flagsのビット16が1の場合に、アドレスフィールドの全部のフィールドが 有効となります。アドレスは物理アドレスです。 | |||
12 | u32 | header_addr | マルチブートヘッダーの先頭が配置される物理アドレスを設定します。 (magicフィールドの値が配置されるメモリーの物理アドレスです)。 |
16 | u32 | load_addr | OSイメージのテキストセグメント(.text)の開始物理アドレスを 設定します。GRUBはOSの実行バイナリだけをロードするために、 OSイメージファイルの先頭から何バイト目に実行バイナリが あるのかを計算するために使用します。 |
20 | u32 | load_end_addr | OSイメージの初期値付きデータセグメント(.data)の最終物理アドレスを 設定します。(load_end_addr - load_addr)は ロードする初期値有りデータのバイト数となります。 初期値有りデータセグメントとテキストセグメントは連続しているものとして GRUBは処理します。 |
24 | u32 | bss_end_addr | 初期値無し変数のデータセグメント(.bss)の最終物理アドレス を設定します。GRUBはこのエリアをゼロで初期化します。 (ANSI C規格に準拠するためなど)。 このフィールドが0に設定されている場合には、GRUBは 初期値無し変数のデータセグメント(.bss)が無いものとして (初期化しません)処理します。 |
28 | u32 | entry_addr | OSをロードした後にジャンプする物理アドレスを設定します。 (カーネルのメイン関数のアドレスを設定します)。 |
グラフィックフィールド | |||
flagsのビット2が1の場合に、グラフィックフィールドの全部のフィールドが 有効となります。OS起動時にカーネルが要求するグラフィックモードを設定します。 | |||
32 | u32 | entry_addr |
0:ブートローダーはグラフィックモードに設定します 1:ブートローダーはEGA標準のテキストモードに設定します その他の値:将来仕様のため予約されています (値が0の場合でもブートローダーはOS起動時にテキストモードに 設定してもよいです。) |
36 | u32 | width |
グラフィックの列数を設定します。 グラフィックモード:ピクセル単位で設定します。 テキストモード:文字数単位で設定します。 (値を0に設定した場合、OSはどのように設定されるかは気にしません) |
40 | u32 | height |
グラフィックの行数を設定します。 グラフィックモード:ピクセル単位で設定します。 テキストモード:文字数単位で設定します。 (値を0に設定した場合、OSはどのように設定されるかは気にしません) |
44 | u32 | depth |
0以外:グラフィックモードの1ピクセル毎のビット数を設定します 0:ビット数をどのように設定されてもOSには問題ありません |
マルチブート仕様で使用する変数の型式 | |
---|---|
型式 | 説明 |
u8 | 符号なし(unsigned)の8ビットデータです |
u16 | 符号なし(unsigned)の16ビットデータです |
u32 | 符号なし(unsigned)の32ビットデータです |
u64 | 符号なし(unsigned)の64ビットデータです |
/* Physical address where kernel is loaded */
#define DEF_MM_KERNEL_PHY_BASEADDR 0x00100000
/* ---------------------------------------------------------------------------------- Magic of Multiboot Header ---------------------------------------------------------------------------------- */
#define DEF_MBH_MAGIC 0x1BADB002
/* ---------------------------------------------------------------------------------- Flags of Multiboot Header ---------------------------------------------------------------------------------- */
#define DEF_MBH_FLAGS_PAGE_ALIGN 0x00000001
/* page (4KB) boundaries */
#define DEF_MBH_FLAGS_MEMORY_INFO 0x00000002
/* memory information */
#define DEF_MBH_FLAGS_VIDEO_MODE 0x00000004
/* video mode */
#define DEF_MBH_FLAGS_AOUT_KLUDGE 0x00010000
/* use address fields */
/* Flags for elf kernel image */
#define DEF_MBH_FLAGS ( DEF_MBH_FLAGS_PAGE_ALIGN | DEF_MBH_FLAGS_MEMORY_INFO )
/* Flags for binary kernel image */
#define DEF_MBH_FLAGS_BIN ( DEF_MBH_FLAGS_PAGE_ALIGN | DEF_MBH_FLAGS_MEMORY_INFO | DEF_MBH_FLAGS_AOUT_KLUDGE )
#define DEF_MBH_CHECKSUM ( - ( DEF_MBH_MAGIC + DEF_MBH_FLAGS ) )
#define DEF_MBH_CHECKSUM_BIN ( - ( DEF_MBH_MAGIC + DEF_MBH_FLAGS_BIN ) )
#define DEF_MBH_HEADER_ADDR DEF_MM_KERNEL_PHY_BASEADDR
#define DEF_MBH_MODE_TYPE 0x00000001
/* text mode */
#define DEF_MBH_WIDTH 0x00000050
/* width = 80 */
#define DEF_MBH_HEIGHT 0x00000028
/* height = 40 */
#define DEF_MBH_DEPTH 0x00000000
/* ================================================================================= The followings are for only C ================================================================================= */
#ifndef __MULTIBOOT__S #ifndef __MULTIBOOT_HEADER_H #define __MULTIBOOT_HEADER_H typedef unsigned int UINT32
/* ================================================================================= Multiboot Header ================================================================================= */
typedef struct { UINT32 magic; UINT32 flags; UINT32 checksum;
/* The followings are only valid if MULTIBOOT_AOUT_KLUDGE is set */
UINT32 header_addr; UINT32 load_addr; UINT32 load_end_addr; UINT32 bss_end_addr; UINT32 entry_addr;
/* The followings are only valid if MULTIBOOT_VIDEO_MODE is set */
UINT32 mode_type; UINT32 width; UINT32 height; UINT32 depth; }MULTIBOOT_HEADER; #endif
/* __MULTIBOOT_HEADER_H */
#endif
/* __MULTIBOOT__S */
#define DEF_MBH_BL_MAGIC 0x2BADB002
/* The magic should be in EAX */
マルチブート情報 | |||
---|---|---|---|
ラベル名 |
オフセット (バイト) |
サイズ (バイト) |
説明 |
flags | 0 | 4 |
ブート情報のフィールドが有効/無効(有り/無し)のフラグです 各ビットが1になっていれば有効(有り)で、0であれば無効(無し)となります ビット0:1であればmem_*フィールドが有効になります ビット1:1であればboot_deviceフィールドが有効になります ビット2:1であればcmdlineフィールドが有効になります ビット3:1であればmods_*フィールドが有効になります ビット4:1であればsymフィールドがa.outカーネルイメージ用の フォーマットになります ビット5:1であればsymフィールドがELFカーネルイメージ用の フォーマットになります ビット6:1であればmmap_*フィールドが有効になります ビット7:1であればdrives_*フィールドが有効になります ビット8:1であればconfig_tableフィールドが有効になります ビット9:1であればboot_loader_nameフィールドが有効になります ビット10:1であればapm_tableフィールドが有効になります ビット11:vbe_*フィールドが有効になります |
mem_lower | 4 | 4 | ローメモリのメモリサイズが格納されています |
mem_upper | 8 | 4 | 拡張メモリ(1MB以降のメモリ領域)のメモリサイズが格納されています |
mmap_length | 44 | 4 | メモリマップ情報のデータ長が格納されています |
mmap_addr | 48 | 4 | メモリマップ情報が格納されているアドレスが格納されています |
/* ================================================================================= Multiboot Info ================================================================================= */
typedef struct { UINT32 flags;
/* multiboot info version number */ /* available memory from BIOS */
UINT32 mem_lower; UINT32 mem_upper; UINT32 boot_device;
/* "root" partition */
UINT32 cmdline;
/* kernel command line */ /* Boot-Module list */
UINT32 mods_count; UINT32 mods_addr; UINT32 syms1; UINT32 syms2; UINT32 syms3;
/* memory mapping buffer */
UINT32 mmap_length; UINT32 mmap_addr;
/* drive info buffer */
UINT32 drives_length; UINT32 drives_addr;
/* ROM configuration table */
UINT32 config_table;
/* bootloader name */
UINT32 boot_loader_name;
/* Video */
UINT32 vbe_control_info; UINT32 vbe_mode_info; UINT32 vbe_mode; UINT32 vbe_interface_seg; UINT32 vbe_interface_off; UINT32 vbe_interface_len; }MULTIBOOT_INFO;
/***************************************************************************** File:multiboot.h Description:Definition of Multiboot header for C and Assembler *****************************************************************************/
#ifndef __MULTIBOOT__H #define __MULTIBOOT__H
/* Physical address where kernel is loaded */
#define DEF_MM_KERNEL_PHY_BASEADDR 0x00100000
/* ================================================================================== DEFINES of Multiboot header for C and Assember ================================================================================== */ /* ---------------------------------------------------------------------------------- Magic of Multiboot Header ---------------------------------------------------------------------------------- */
#define DEF_MBH_MAGIC 0x1BADB002
/* magic */ /* ---------------------------------------------------------------------------------- Flags of Multiboot Header ---------------------------------------------------------------------------------- */
#define DEF_MBH_FLAGS_PAGE_ALIGN 0x00000001
/* page (4KB) boundaries */
#define DEF_MBH_FLAGS_MEMORY_INFO 0x00000002
/* memory information */
#define DEF_MBH_FLAGS_VIDEO_MODE 0x00000004
/* video mode */
#define DEF_MBH_FLAGS_AOUT_KLUDGE 0x00010000
/* use address fields */ /* ---------------------------------------------------------------------------------- Other fileds of Multiboot Header ---------------------------------------------------------------------------------- */ /* Flags for elf kernel image */
#define DEF_MBH_FLAGS ( DEF_MBH_FLAGS_PAGE_ALIGN | DEF_MBH_FLAGS_MEMORY_INFO )
/* Flags for binary kernel image */
#define DEF_MBH_FLAGS_BIN ( DEF_MBH_FLAGS_PAGE_ALIGN | DEF_MBH_FLAGS_MEMORY_INFO | DEF_MBH_FLAGS_AOUT_KLUDGE ) #define DEF_MBH_CHECKSUM ( - ( DEF_MBH_MAGIC + DEF_MBH_FLAGS ) ) #define DEF_MBH_CHECKSUM_BIN ( - ( DEF_MBH_MAGIC + DEF_MBH_FLAGS_BIN ) )
/* The following fields are unnecessory for elf format */
#define DEF_MBH_HEADER_ADDR DEF_MM_KERNEL_PHY_BASEADDR #define DEF_MBH_MODE_TYPE 0x00000001
/* text mode */
#define DEF_MBH_WIDTH 0x00000050
/* width = 80 */
#define DEF_MBH_HEIGHT 0x00000028
/* height = 40 */
#define DEF_MBH_DEPTH 0x00000000 #endif
/* __MULTIBOOT__H */ /* ================================================================================= The followings are for only C ================================================================================= */
#ifndef __MULTIBOOT__S #ifndef __MULTIBOOT_HEADER_H #define __MULTIBOOT_HEADER_H typedef unsigned int UINT32;
/* ================================================================================= Multiboot Header ================================================================================= */
typedef struct { UINT32 magic; UINT32 flags; UINT32 checksum;
/* The followings are only valid if MULTIBOOT_AOUT_KLUDGE is set */
UINT32 header_addr; UINT32 load_addr; UINT32 load_end_addr; UINT32 bss_end_addr; UINT32 entry_addr;
/* The followings are only valid if MULTIBOOT_VIDEO_MODE is set */
UINT32 mode_type; UINT32 width; UINT32 height; UINT32 depth; }MULTIBOOT_HEADER;
/* ================================================================================= Multiboot Info ================================================================================= */
typedef struct { UINT32 flags;
/* multiboot info version number */ /* available memory from BIOS */
UINT32 mem_lower; UINT32 mem_upper; UINT32 boot_device;
/* "root" partition */
UINT32 cmdline;
/* kernel command line */ /* Boot-Module list */
UINT32 mods_count; UINT32 mods_addr; UINT32 syms1; UINT32 syms2; UINT32 syms3;
/* memory mapping buffer */
UINT32 mmap_length; UINT32 mmap_addr;
/* drive info buffer */
UINT32 drives_length; UINT32 drives_addr;
/* ROM configuration table */
UINT32 config_table;
/* bootloader name */
UINT32 boot_loader_name;
/* Video */
UINT32 vbe_control_info; UINT32 vbe_mode_info; UINT32 vbe_mode; UINT32 vbe_interface_seg; UINT32 vbe_interface_off; UINT32 vbe_interface_len; }MULTIBOOT_INFO; #endif
/* __MULTIBOOT_HEADER_H */
#endif
/* __MULTIBOOT__S */
/********************************************************************************* File:multiboot.s Description:Multiboot Header *********************************************************************************/
#define __MULTIBOOT__S 1 #include "multiboot.h"
/* kernel entry */
.extern _kernel_entry
/* ================================================================================== Prototype Statement ================================================================================== */ /* Open Functions */ /* Local Functions */ /* ================================================================================== DEFINE ================================================================================== */ /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < open functions > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
.text .code32 .globl start, _start
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :start, _start Input :void Output :void Return :void Description :void _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
start: _start: jmp _multi_boot_entry
/* align 32 bits boundary */
.align 4
/* ================================================================================== multiboot header ================================================================================== */
multiboot_header: .long DEF_MBH_MAGIC .long DEF_MBH_FLAGS .long DEF_MBH_CHECKSUM
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :_multi_boot_entry Input :void Output :void Return :void Description :void _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
_multi_boot_entry:
/* ------------------------------------------------------------------------ */ /* reset eflags */ /* ------------------------------------------------------------------------ */
pushl $0 popf
/* ------------------------------------------------------------------------ */ /* push the pointer to the multiboot information */ /* ------------------------------------------------------------------------ */
pushl %ebx # 1st argument pushl %eax # 2nd argument call _kernel_entry loop_infinite: hlt jmp loop_infinite
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < Local Functions > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* ================================================================================== Funtion :void Input :void Output :void Return :void Description :void ================================================================================== */
#define __MULTIBOOT__S 1
#include "multiboot.h"
/* kernel entry */
.extern _kernel_entry
.text
.code32
.globl start, _start
start:
_start:
jmp _multi_boot_entry
multiboot_header:
.long DEF_MBH_MAGIC
.long DEF_MBH_FLAGS
.long DEF_MBH_CHECKSUM
_multi_boot_entry:
/* ------------------------------------------------------------------------ */ /* reset eflags */ /* ------------------------------------------------------------------------ */
pushl $0 popf
/* ------------------------------------------------------------------------ */ /* push the pointer to the multiboot information */ /* ------------------------------------------------------------------------ */
pushl %ebx # 1st argument pushl %eax # 2nd argument
call _kernel_entry
loop_infinite:
hlt
jmp loop_infinite
/********************************************************************************* File:kernel.c Description:Kernel entry *********************************************************************************/
#include "multiboot.h"
/* ================================================================================== Prototype Statement ================================================================================== */ /* Open Functions */ /* Local Functions */
void displaySample( char c, unsigned char foreColor, unsigned char backColor, int x, int y );
/* ================================================================================== DEFINE ================================================================================== */
#define VRAM_TEXTMODE 0x000B8000 #define DEF_COLOR_BLACK 0x00 #define DEF_COLOR_WHITE 0x0F #define MAX_Y 25 #define MAX_X 80 #define MAX_XY (80*25)
/* ================================================================================== Management ================================================================================== */
char message[ ] = "Hello world!";
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < open functions > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :_kernel_entry Input :UINT32 magic < magic number of multiboot > MULTIBOOT_INFO *info < multiboot information structure > Output :void Return :void Description :kernel entry _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void _kernel_entry( UINT32 magic, MULTIBOOT_INFO *info ) { int strlen; int i; strlen = sizeof( message ); for( i = 0 ; i < strlen ; i++ ) { displaySample( message[ i ], DEF_COLOR_WHITE, DEF_COLOR_BLACK, i, 0 ); } for( ; ; ); }
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < Local Functions > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* ================================================================================== Funtion :displaySample Input :char c < a character to print > unsigned char foreColr < foreground color > unsigned char backColor < background color > int x < x-axis position where a character is printed > int y < y-axis position where a character is printed > Output :void Return :void Description :print a character with setting color in text mode ================================================================================== */
void displaySample( char c, unsigned char foreColor, unsigned char backColor, int x, int y ) { unsigned short *vram_TextMode; unsigned short color; vram_TextMode = ( unsigned short *)VRAM_TEXTMODE; color = ( backColor << 4 ) | ( foreColor & 0x0F ); vram_TextMode += x + y * MAX_X; *vram_TextMode = ( color << 8 ) | c; }
i686-pc-linux-gnu-gcc -c -o multiboot.o multiboot.S
i686-pc-linux-gnu-gcc -c -o kernel.o kernel.c
$ i686-pc-linux-gnu-ld -Ttext=0x100000 multiboot.o kernel.o -o KImage
/* ================================================================================== multiboot header ================================================================================== */
multiboot_header: .long DEF_MBH_MAGIC .long DEF_MBH_FLAGS_BIN .long DEF_MBH_CHECKSUM_BIN .long multiboot_header .long _start .long _data_end .long _bss_end .long _multi_boot_entry
SECTIONS
{
. = 0x100000;
.text :
{
_text_start = .;
*(.text)
_text_end = .;
}
.rodata :
{
_rodata_start = .;
*(.rodata)
_rodata_end = .;
}
.data :
{
_data_start = .;
*(.data)
_data_end = .;
}
.bss :
{
_bss_start = .;
*(.bss)
_bss_end = .;
}
}
$ i686-pc-linux-gnu-gcc -c -o multiboot_bin.o multiboot_bin.S
i686-pc-linux-gnu-ld -T linkerscript --oformat=binary multiboot_bin.o kernel.o -o KImagebin