設定使用initrd後, .config
LINUX_CONFIG_ROOTFS="initrd"在config/kernel-config-initrd ..大概會用這個作kernel defaultconfig file吧。
CONFIG_ROOTFS_INITRD=y
diff一下romfs和initrd..
CMDLINE="root=/dev/ram0 rw"應該是make linux-config時,block device的"RAM disk data block compiled in"這個 option吧。
BLK_DEV_RAM=y
BLK_DEV_RAM_SIZE=4096
BLK_DEV_INITRD=y
BLK_DEV_RAMDISK_DATA=y
#BLK_DEV_BLKMEM
這個option configure在 drivers/block/Config.h
dep_bool 'RAM disk data block compiled in' CONFIG_BLK_DEV_RAMDISK_DATA所以好像有兩種initrd使用的方式:
- 將initrd image和kernel 綁在一起。(append在kernel後面)
- 另外存放,但是需要另外告訴kernel initrd image所在位置(memory address)
#ifdef CONFIG_BLK_DEV_INITRD__ramdisk_data, __ramdisk_data_end 這兩個 label 定義在
// let the kernel know where the initrd exists
#ifdef CONFIG_SD_INITRD_EMBED
{
initrd_start = (unsigned long) &__ramdisk_data;
initrd_end = (unsigned long) &__ramdisk_data_end - (unsigned long) &__ramdisk_data;
}
#else
initrd_start = CONFIG_SD_INITRD_START;
initrd_end = CONFIG_SD_INITRD_START + CONFIG_SD_INITRD_SIZE;
#endif
#endif
arch/armnommu/vmlinux-armv.lds.in:
SECTIONS.可以看到在link時,會將INITRDIMAGE link進來。依照image的size決定__ramdisk_data, __ramdisk_data_end.
{
. = TEXTADDR;
.init : { /* Init code and data */
_stext = .;
__略__
__ramdisk_data = .;
INITRDIMAGE
__ramdisk_data_end = .;
. = ALIGN(4096);
__init_end = .;
}
另一個,不將initrd 和kernel link在一起的方法,則是在configure時define CONFIG_SD_INIT_START 和 CONFIG_SD_INIT_SIZE。
所以重點就在...
- enable kernel 對RAM disak, initrd的支援
- 傳入適當的boot cmd
root= 在 init/do_mounts.c : __setup("root=", root_dev_setup);
static int __init root_dev_setup(char *line)name_to_kdev_t( )就是把 device name string轉為 device MAJ/MIN number。
{
int i;
char ch;
ROOT_DEV = name_to_kdev_t(line);
memset (root_device_name, 0, sizeof root_device_name);
if (strncmp (line, "/dev/", 5) == 0) line += 5;
for (i = 0; i < sizeof root_device_name - 1; ++i)
{
ch = line[i];
if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
root_device_name[i] = ch;
}
return 1;
}
kernel 認識的devname--MAJ/MIN 宣告在 root_dev_names[].
root_dev_setup( ) 由cmdline設定好 ROOT_DEV 跟 root_device_name[].
..找到這裡對initrd而言好像有點不對..
init/main.c/init( )
do_basic_setup( ); 由cmdline找到root的MAJ/MIN number.
prepare_namespace( );
完成!
linux config時要enable RAMDISK, INITRD, EMBEDDED INITRD.
進入magsi 特殊config時,要選 Embedded INITRD image.
這樣build出來的linux.bin會包含linux kernel image 和 initrd (內含root ).
用bootloader command : download net kernel linux.bin
download到kernel target(特殊address)後。
用bootloader command : boot kernel
就可以執行了。
從boot message可以看到mount initrd作root的動作。
但是奇怪的是:console竟然不能用。不能輸入。
在init.d中啟動telnetd,login是ok的。
換一個ssh開啟minicom後OK。
所以大概是VM的問題。
這樣的作法在RAM足夠多,但是flash size不夠時可以使用。
因為bootloader內含gunzip。所以整個root都可以zip起來,節省flash size。
boot後再unzip到ram中執行。
若是用romfs,因為無法kernel要直接mount,所以不能壓縮。順便說明一下bootloader的動作:
這個bootloader要是要從flash中啟動,只有支援rootfs系統。
bootloader在flash中找romfs keyword,當作romfs起始。
再在romfs中找到linux.bin(.gz)。解開(或copy)到ram中,將控制權交給ram中的kernel。
所以即使是 linux.bin 含 initrd,要燒到flash中讓bootloader boot。也要再pack成romfs,才可以燒到flash中(雖然這個romfs中只有linux.bin一個檔案)。
沒有留言:
張貼留言