Linux起動の概要
Linux起動前
Linuxでは基本的にシステムの初期設定をするので、
Linux以前ではLinuxをロードする対象であるSDRAM領域を初期化する処理は必要となります。一般的な組込みLinuxボードでは大容量フラッシュROM上にLinuxカーネルが書き込まれていることが多いので、
SH7706LSRボードでは大容量フラッシュROMではなくSDカード上にLinuxカーネルがファイルとして書き込まれていますので、
初期RAMDISK
Linuxが起動すると、
たとえば、
ミニLinuxシステムの処理は、
initプロセス
本稼働のファイルシステム上でLinuxが起動すると、
Linuxシステムの初期化処理は、
組込みLinuxの起動について
PCの場合はLILOやgrubをそのままのかたちで利用すればLinuxが起動できますので、
組込みボードでのLinux起動へのアプローチには、
もう1つは、
Linuxのロード場所
Linuxの実体は、
まず、
そうすると、
答えはMMUにあります。前回MMUについて解説したと思いますが、
カーネルの物理構造
組込みボード上でLinuxを起動させるローダーを開発する場合は、

Linuxカーネルは図1のような構造になっています。Linuxカーネルは市販デバッガでもソースコードデバッグなどができるようにそれ自身ELF形式になっていますので、
Linuxカーネルは起動時に必須なパラメータ指定はLinuxカーネルの先頭から1000H番地から始まる整数配列に数値を格納し、
これでLinuxカーネルが起動します。
ブートローダ
カーネルパラメータ仕様
Linuxは基本的にPCをターゲットとしていますので、
今回のブートローダで使う部分は初期RAMDISKに関する部分のみとなります。カーネルパラメータはLinuxカーネルのオフセット1000Hから始まる4バイト整数の配列で指定します。それぞれのパラメータは以下のような内容になっています。
- 0番目 : MOUNT_
ROOT_ RDONLY - 読み込み専用でルートファイルシステムをマウントするかどうかを設定し、
MS_ RDONLYビット (ビット0) で読み込み専用に設定します。 - 1番目 : RAMDISK_
FLAGS - 初期RAMDISKの設定で、
RAMDISK_ PROMPT_ FLAG (ビット15) で初期RAMDISKのプロンプトを設定、 RAMDISK_ LOAD_ FLAG (ビット14) で初期RAMDISKを使うことを設定します。 - 2番目 : ORIG_
ROOT_ DEV - ルートデバイスのデバイスをメジャー番号とマイナー番号で設定します。
- 3番目 : LOADER_
TYPE - ブートローダのタイプを設定しますが、
組込みボードの場合は、 通常、 設定不要です。 - 4番目 : INITRD_
START - 初期RAMDISKの開始番地を指定します。
- 5番目 : INITRD_
SIZE - 初期RAMDISKの開始番地のサイズを指定します。
ブートローダの実際
SH7706ボードにおけるLinuxブートローダの例はリスト1のとおりになっています。Linuxブートローダのソースコードにはコメントが記入されていますので、
1: #include <macro.h>
2: #include <mes2.h>
3: #include <h8/reg770x.h>
4: #include <string.h>
5:
6: #define RAMDISK_PROMPT_FLAG 0x8000
7: #define RAMDISK_LOAD_FLAG 0x4000
8:
9: int main(int argc, char **argv) {
10: int fd, size, *param, rdsize, c;
11: char *ptr, *mem, *rdptr, ram;
12: void (*func)();
13:
14: // 初期RAMDISKの先頭アドレスの初期化
15: rdptr = 0;
16:
17: // 初期RAMDISKのサイズの初期化
18: rdsize = 0;
19:
20: // 初期RAMディスクのイメージファイルを開く
21: fd = open("initrd.img", OptRead);
22:
23: // 初期RAMディスクのイメージファイルの有無を判定
24: if(fd != -1) {
25: // 初期RAMディスクが存在する場合
26:
27: // 初期RAMDISKのファイルサイズを格納
28: rdsize = GetFileSize(fd);
29:
30: // 初期RAMDISKのためのメモリ領域を確保
31: rdptr = malloc(rdsize);
32:
33: if(rdptr == 0) {
34:
35: // 初期RAMDISKのためのメモリ領域を確保できない場合は異常終了させる
36: printf("No memory\r");
37: close(fd);
38: return -1;
39: }
40:
41: // 初期RAMDISKロードのメッセージ出力
42: printf("initrd loading.");
43:
44: // 初期RAMDISKイメージファイルを読み込みメモリ領域に4000Hずつコピー
45: mem = rdptr;
46: c = 0;
47: do {
48: size = read(fd, mem, 0x4000);
49: mem = &mem[0x4000];
50:
51: // 進捗状況を逐次表示
52: if((++c & 0x7) == 0) putchar('.');
53: } while(size == 0x4000);
54: putchar('¥r'), putchar('¥n');
55:
56: // 初期RAMDISKイメージファイルを閉じる
57: close(fd);
58: }
59:
60: // カーネルヘッダ領域データを保管するためのメモリを確保
61: ptr = malloc(0x2000);
62: if(ptr == 0) {
63:
64: // カーネルヘッダ領域データのためのメモリ領域を確保できない場合は異常終了させる
65: printf("No memory¥r");
66: return -1;
67: }
68:
69: // カーネルパラメータ領域のポインタをセット
70: param = (int*)(ptr + 0x1000);
71:
72: // Linuxカーネルのイメージファイルを開く
73: fd = open("vmlinux", OptRead);
74:
75: // Linuxカーネルのイメージファイルの有無を判定
76: if(fd == -1) {
77:
78: // Linuxカーネルが存在しない場合は異常終了させる
79: free(ptr);
80: printf("No vmlinux¥r¥n");
81: return -1;
82: }
83:
84: // カーネルヘッダ領域データをメモリに読み込む
85: read(fd, ptr, 0x2000);
86:
87: // カーネルオプションの内容をオフセット1100Hへセットする
88: strcpy(ptr + 0x1100, "mem=32M console=ttySC1,115200 root=/dev/shmmc2");
89:
90: // カーネルコード領域をロードするためのメモリアドレスの先頭をセット
91: mem = (char*)0x8c002000;
92:
93: // カーネルを実行するためのアドレスをセット
94: func = (void*)0x8c002000;
95:
96:
97: // カーネルロードのメッセージ出力
98: printf("vmlinux loading.");
99:
100: // カーネルイメージファイルを読み込みメモリ領域に4000Hずつコピー
101: c = 0;
102: do {
103: size = read(fd, mem, 0x4000);
104: mem = &mem[0x4000];
105:
106: // 進捗状況を逐次表示
107: if((++c & 0x7) == 0) putchar('.');
108: } while(size == 0x4000);
109: putchar('¥r'), putchar('¥n');
110:
111: // カーネルイメージファイルを閉じる
112: close(fd);
113:
114: // 初期RAMDISKの有無を判定
115: if(rdsize > 0) {
116:
117: // 初期RAMDISKに関するカーネルパラメータの設定
118: param[1] = RAMDISK_PROMPT_FLAG | RAMDISK_LOAD_FLAG;
119: param[4] = (int)rdptr & 0x3ffffff;
120: param[5] = rdsize;
121: }
122:
123: // 時間待ち
124: sleep(500);
125:
126: // CPUでの割り込みを禁止しMESの動作を止める
127: INT_DISABLE();
128:
129: // ウオッチドッグタイマーを止める
130: WTCSR_WR = 0x8500;
131:
132: // 全ての割り込みを禁止する
133: IPRA = 0;
134: IPRB = 0;
135: IPRC = 0;
136: IPRD = 0;
137: IPRE = 0;
138:
139: // カーネルヘッダ領域データを保管した領域からカーネルヘッダ領域へコピー
140: memcpy((char*)0x8c000000, ptr, 0x2000);
141:
142: // カーネルコード領域の先頭へジャンプ
143: (*func)();
144: }
Linuxブートローダでは最初に初期RAMDISKのファイルイメージを任意のメモリ領域に読み込み、
次にLinuxカーネルのファイルイメージからヘッダ部分である最初の2000Hのサイズを任意のメモリ領域へ読み込み、
このブートローダはMESで動作していますので、
次回は
次回はルートファイルシステムの構築について解説します。