📄 linux.c
字号:
blocks_per_group, inodes_per_group, group_desc_sector, first_inode_table, inode_table_sector, dir_entry_table_sector, inode, group, file_size, file_block[15], file_data_sector, addr_per_block; ext2_super_block *psb; ext2_group_desc *pgd; ext2_inode *pinode; ext2_dir_entry *pde = 0; addr_t load_address; char *flash_option[] = { 0, mem,#if !defined(CONSOLE) || (defined(CONSOLE) && CONSOLE == 1) console,#endif }; char *cf_option[] = { 0, mem, noinitrd, root,#if !defined(CONSOLE) || (defined(CONSOLE) && CONSOLE == 1) console,#endif }; if (!argc) { if (*(volatile unsigned char *)(0x80000000 + PDDR) & PDDR_FLASHBOOT) { argc = sizeof (flash_option) / sizeof (char *); argv = flash_option; } else { if (ide_detect_devices ()) { return 0; } if (ide_startup_devices ()) { return 0; } if (ide_read_sectors (0, 0, buf, 1)) { return 0; } IO_LEDFLSH = 0x4c; memcpy (part, buf + 0x1be, sizeof(partition) * 4); for (i = 0; i < 4; i++) { if (part[i].sys_ind != 0x83) { continue; } start = read4_little_endian (part[i].start4); size = read4_little_endian (part[i].size4); hprintf ("/dev/hda%d: start=0x%x, size=0x%x\n", i + 1, start, size); super_block_sector = start + 2; if (ide_read_sectors (0, super_block_sector, buf, 1)) { hprintf ("Super block read error.\n"); continue; } psb = (ext2_super_block *)buf; if (psb->s_magic != 0xef53) { hprintf ("Isn't ext2.\n"); continue; } if (psb->s_inode_size != INODE_SIZE) { hprintf ("Bad inode size.\n"); continue; } if (psb->s_log_block_size > 2) { hprintf ("Bad block size.\n"); continue; } sectors_per_block = 2; for (j = 0; j < psb->s_log_block_size; j++) { sectors_per_block *= 2; } blocks_per_group = psb->s_blocks_per_group; inodes_per_group = psb->s_inodes_per_group; group_desc_sector = start + sectors_per_block * (1 + psb->s_first_data_block); if (ide_read_sectors (0, group_desc_sector, buf, 1)) { hprintf ("Group desc read error.\n"); continue; } pgd = (ext2_group_desc *)buf; first_inode_table = pgd->bg_inode_table; inode_table_sector = start + sectors_per_block * first_inode_table; if (ide_read_sectors (0, inode_table_sector, buf, 1)) { hprintf ("Inode table read error.\n"); continue; } for (j = 0; j < SECTOR_SIZE; j += INODE_SIZE) { pinode = (ext2_inode *)(buf + j); if ((pinode->i_mode & 0xf000) == 0x4000) { break; } } if (j >= SECTOR_SIZE) { hprintf ("Can't find root.\n"); continue; } dir_entry_table_sector = start + sectors_per_block * pinode->i_block[0]; if (ide_read_sectors (0, dir_entry_table_sector, buf, sectors_per_block)) { hprintf ("Root directory entry read error.\n"); continue; } for (pde = (ext2_dir_entry *)buf; (addr_t)pde - (addr_t)buf <= SECTOR_SIZE * sectors_per_block - 12; pde = (ext2_dir_entry *)(((addr_t)pde) + pde->rec_len)) { if (!pde->rec_len) { break; } if (pde->name_len == 4) { if (pde->name[0] == 'b' && pde->name[1] == 'o' && pde->name[2] == 'o' && pde->name[3] == 't') { break; } } } if ((addr_t)pde - (addr_t)buf > SECTOR_SIZE * sectors_per_block - 12) { hprintf ("Can't find /boot\n"); continue; } if (!pde->rec_len) { hprintf ("Can't find /boot\n"); continue; } group = (pde->inode - 1) / inodes_per_group; inode = (pde->inode - 1) % inodes_per_group; inode_table_sector = start + sectors_per_block * (blocks_per_group * group + first_inode_table) + inode / (SECTOR_SIZE / INODE_SIZE); if (ide_read_sectors (0, inode_table_sector, buf, 1)) { hprintf ("Inode table read error.\n"); continue; } pinode = (ext2_inode *) (buf + INODE_SIZE * (inode % (SECTOR_SIZE / INODE_SIZE))); if ((pinode->i_mode & 0xf000) != 0x4000) { hprintf ("/boot is not directory.\n"); continue; } dir_entry_table_sector = start + sectors_per_block * pinode->i_block[0]; if (ide_read_sectors (0, dir_entry_table_sector, buf, sectors_per_block)) { hprintf ("/boot directory entry read error.\n"); continue; } for (pde = (ext2_dir_entry *)buf; (addr_t)pde - (addr_t)buf <= SECTOR_SIZE * sectors_per_block - 16; pde = (ext2_dir_entry *)(((addr_t)pde) + pde->rec_len)) { if (!pde->rec_len) { break; } if (pde->name_len == 5 || pde->name_len == 8) { if (pde->name[0] == 'I' && pde->name[1] == 'm' && pde->name[2] == 'a' && pde->name[3] == 'g' && pde->name[4] == 'e') { if (pde->name_len == 5) { gzimage = 0; break; } if (pde->name[5] == '.' && pde->name[6] == 'g' && pde->name[7] == 'z') { gzimage = 1; break; } } } } if ((addr_t)pde - (addr_t)buf > SECTOR_SIZE * sectors_per_block - 16) { hprintf ("Can't find /boot/Image(.gz)\n"); continue; } if (!pde->rec_len) { hprintf ("Can't find /boot/Image(.gz)\n"); continue; } group = (pde->inode - 1) / inodes_per_group; inode = (pde->inode - 1) % inodes_per_group; inode_table_sector = start + sectors_per_block * (blocks_per_group * group + first_inode_table) + inode / (SECTOR_SIZE / INODE_SIZE); if (ide_read_sectors (0, inode_table_sector, buf, 1)) { hprintf ("Inode table read error.\n"); continue; } pinode = (ext2_inode *) (buf + INODE_SIZE * (inode % (SECTOR_SIZE / INODE_SIZE))); if ((pinode->i_mode & 0xf000) != 0x8000) { hprintf ("/boot/Image%s is not file.\n", (!gzimage) ? "" : ".gz"); continue; } file_size = pinode->i_size; if (file_size <= 0) { hprintf ("/boot/Image%s size is zero.\n", (!gzimage) ? "" : ".gz"); continue; } if (file_size > INITRD_LOAD_ADDRESS - LINUX_LOAD_ADDRESS) { hprintf ("/boot/Image%s size is too large.\n", (!gzimage) ? "" : ".gz"); continue; } hprintf ("/boot/Image%s is found.\n", (!gzimage) ? "" : ".gz"); for (j = 0; j < 15; j++) { file_block[j] = pinode->i_block[j]; } load_address = (!gzimage) ? LINUX_LOAD_ADDRESS : INITRD_LOAD_ADDRESS; hprintf ("Copying kernel"); if (copy_file (12, file_block, start, sectors_per_block, &file_size, &load_address)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); continue; } if (file_size <= 0) { gunzip_kernel = 0; break; } file_data_sector = start + sectors_per_block * file_block[12]; if (ide_read_sectors (0, file_data_sector, buf, sectors_per_block)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); continue; } addr_per_block = (SECTOR_SIZE * sectors_per_block) / sizeof(unsigned long); if (copy_file (addr_per_block, (unsigned long *)buf, start, sectors_per_block, &file_size, &load_address)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); continue; } if (file_size <= 0) { gunzip_kernel = 0; break; } file_data_sector = start + sectors_per_block * file_block[13]; if (ide_read_sectors (0, file_data_sector, buf2, sectors_per_block)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); continue; } for (j = 0; j < addr_per_block && file_size > 0; j++) { file_data_sector = start + sectors_per_block * *(((unsigned long *)buf2) + j); if (ide_read_sectors (0, file_data_sector, buf, sectors_per_block)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); break; } if (copy_file (addr_per_block, (unsigned long *)buf, start, sectors_per_block, &file_size, &load_address)) { hprintf ("/boot/Image%s data read error.\n", (!gzimage) ? "" : ".gz"); break; } } if (file_size <= 0) { gunzip_kernel = 0; break; } hprintf ("/boot/Image%s size is too large.\n", (!gzimage) ? "" : ".gz"); continue; } IO_LEDFLSH = 0x0; if (gunzip_kernel) { return (0); } hprintf ("done.\n"); if (gzimage) { boost_on (); gunzip_object (" kernel", INITRD_LOAD_ADDRESS, LINUX_LOAD_ADDRESS); boost_off (); } argc = sizeof (cf_option) / sizeof (char *); root[sizeof (root) - 2] = '1' + i; argv = cf_option; } } if (argc < 1) return -H_EUSAGE; boost_on (); if (gunzip_kernel) { gunzip_object (" kernel", LINUX_SRC_ADDRESS, LINUX_LOAD_ADDRESS); } { int c = argc; char **v = argv; while (--c > 0) { if (!strcmp (*++v, "noinitrd")) { break; } } if (c <= 0) { gunzip_object ("ramdisk", INITRD_SRC_ADDRESS, INITRD_LOAD_ADDRESS); } else { bytes_out = 0; } } boost_off (); linux_cmdfunc (argc, argv); return 0;}const command_t linux_command = { "linux", "<linux options>", "start Linux", &linux_cmdfunc };const command_t boot_command = { "boot", "", "boot default Linux kernel and ramdisk", &boot_cmdfunc };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -