커널이 initrd를 찾을 수 없나요?

커널이 initrd를 찾을 수 없나요?

ext2를 마운트하려고 하면 다음 오류가 발생합니다.

Creating 4 MTD partitions on "MPC8313RDB Flash Map Info":
0x000000000000-0x000000100000 : "U-Boot"
0x000000100000-0x000000300000 : "Kernel"
0x000000300000-0x000000700000 : "JFFS2"
0x000000700000-0x000000800000 : "dtb"
List of all partitions:
1f00            1024 mtdblock0  (driver?)
1f01            2048 mtdblock1  (driver?)
1f02            4096 mtdblock2  (driver?)
1f03            1024 mtdblock3  (driver?)
No filesystem could mount root, tried:  ext2
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)

어떤 이유로 u-boot는 부팅 매개변수를 커널에 전달할 수 없으므로 init/main.c의 boot_command_line을 수정하여 직접 지정합니다. 매개변수는 다음과 같습니다.

root=/dev/ram0 rw rootfstype=ext2 ramdisk_size=30000 ramdisk_blocksize=1024 console=ttyS0,115200

나는 커널에 initrd에 대한 충분한 정보가 없다는 것이 문제라고 생각했습니다(그리고 지금도 생각합니다). 그래서 powerpc/boot/of.c를 늘리고 수동으로 설정했습니다.

loader_info
        if (a1 && a2 && a2 != 0xdeadbeef) {
                //loader_info.initrd_addr = a1;
                //loader_info.initrd_size = a2;
        loader_info.initrd_addr= 0x07c15000;
        loader_info.initrd_size= 0x00386815;
        }

u-boot에서 보고한 크기와 위치이기 때문에 이 값을 선택했습니다.

Loading Ramdisk to 07c15000, end 07f9b815 ... OK

rootfstype을 지정하지 않으면 기본값은 yaffs2이고 출력은 다음과 같습니다.

yaffs: dev is 1048576 name is "ram0" rw
yaffs: passed flags ""
yaffs: dev is 1048576 name is "ram0" rw
yaffs: passed flags ""
yaffs: mtd is read only, setting superblock read only
------------[ cut here ]------------
WARNING: at mm/page_alloc.c:2544
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 3.16.62 #116
task: c782c000 ti: c781a000 task.ti: c781a000
NIP: c006dcc0 LR: c006d754 CTR: 00000000
REGS: c781b890 TRAP: 0700   Not tainted  (3.16.62)
MSR: 00029032 <EE,ME,IR,DR,RI>  CR: 22002244  XER: 00000000

GPR00: c006d754 c781b940 c782c000 00000000 00000001 00000000 c781b8a8 00000041
GPR08: c02a46ab 00000000 00000001 00000000 22002242 00000000 c00041a0 00000000
GPR16: 00000000 00000000 00000000 00000041 00024050 c02a45ec c02bbb40 c02bbb3c
GPR24: 00000000 00000014 00000000 00000000 c02a45e8 c02b10e0 00004050 00000001
NIP [c006dcc0] __alloc_pages_nodemask+0x660/0x86c
LR [c006d754] __alloc_pages_nodemask+0xf4/0x86c
Call Trace:
[c781b940] [c006d754] __alloc_pages_nodemask+0xf4/0x86c (unreliable)
[c781ba10] [c007f51c] kmalloc_order+0x18/0x4c
[c781ba20] [c01128bc] yaffs_tags_marshall_read+0x22c/0x264
[c781bae0] [c0110650] yaffs2_checkpt_find_block+0x90/0x1a8
[c781bb50] [c011125c] yaffs2_checkpt_rd+0x200/0x228
[c781bbe0] [c0114dcc] yaffs2_rd_checkpt_validity_marker+0x24/0xa4
[c781bc10] [c0115b68] yaffs2_checkpt_restore+0x68/0x714
[c781bc80] [c010fe90] yaffs_guts_initialise+0x46c/0x868
[c781bcb0] [c0108810] yaffs_internal_read_super.isra.16+0x420/0x83c
[c781bd50] [c0108c48] yaffs2_internal_read_super_mtd+0x1c/0x3c
[c781bd60] [c00a6224] mount_bdev+0x194/0x1c0
[c781bdb0] [c00a6c60] mount_fs+0x20/0xb8
[c781bdd0] [c00be984] vfs_kern_mount+0x54/0x120
[c781bdf0] [c00c1a30] do_mount+0x1f0/0xb60
[c781be50] [c00c2770] SyS_mount+0xac/0x120
[c781be90] [c0275e94] mount_block_root+0x130/0x2a0
[c781bee0] [c027635c] prepare_namespace+0x1b8/0x200
[c781bf00] [c0275b48] kernel_init_freeable+0x1a8/0x1bc
[c781bf30] [c00041b8] kernel_init+0x18/0x120
[c781bf40] [c000e310] ret_from_kernel_thread+0x5c/0x64
Instruction dump:
2f890000 40beff90 89210030 2f890000 419efe3c 4bffff80 73ca0200 4082fab4
3d00c02a 390846ab 89480001 694a0001 <0f0a0000> 2f8a0000 419efa98 39400001
---[ end trace fbbfd1e0d42ac49d ]---
VFS: Mounted root (yaffs2 filesystem) readonly on device 1:0.
devtmpfs: error mounting -2
Freeing unused kernel memory: 112K (c0275000 - c0291000)

이 문제의 근원은 무엇입니까?

답변1

어떤 이유에서인지 내 U-boot는 initrd가 RAM에 로드되는 위치를 커널에 알리지 않으므로 setup-common.c에서 initrd_start 및 initrd_end를 수동으로 설정했습니다. 램디스크에 의해 로드된 램의 메모리 위치를 커널의 가상 주소 공간에 매핑했습니다. PAGE_OFFSET이 램디스크 주소보다 크기 때문에 다시 매핑해야 합니다.

void __init check_for_initrd(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
initrd_start= (int)ioremap(0x07c15000 ,(0x07f9b815-0x07c15000) );
initrd_end= initrd_start + (0x07f9b815 - 0x07c15000);
printk("PAGE OFFSET: %lx\n", PAGE_OFFSET);
DBG(" -> check_for_initrd()  initrd_start=0x%lx  initrd_end=0x%lx\n",
    initrd_start, initrd_end);

관련 정보