慢慢欣赏linux x86 bootloader加载kernel的策略
对于老的x86来说,bootloader把内核看成两部分,实模式部分和保护模式部分。bootloader分别把实模式和保护模式加载到内存的不同地方,然后跳转到实模式部分。实模式最后跳转到保护模式部分。
不同的bootloader必须都按照这个规矩来。
下面以uboot为例讲解流程
struct boot_params *load_zimage(char *image, unsigned long kernel_size, ulong *load_addressp)
=>setup_base = (struct boot_params *)DEFAULT_SETUP_BASE;/* base address for real-mode segment */
/*
* Memory lay-out:
*
* relative to setup_base (which is 0x90000 currently)
*
* 0x0000-0x7FFF Real mode kernel
* 0x8000-0x8FFF Stack and heap
* 0x9000-0x90FF Kernel command line
*/
=>/* determine size of setup *///决定内核实模式程序setup.bin的大小
if (0 == hdr->setup_sects) {
printf("Setup Sectors = 0 (defaulting to 4)\n");
setup_size = 5 * 512;
} else {
setup_size = (hdr->setup_sects + 1) * 512;
}
=>bootproto = get_boot_protocol(hdr);//老内核需要执行setup.bin,新内核应该可以直接进入保护模式,只有hdr等参数有用
=>/* Determine image type */
big_image = (bootproto >= 0x0200) &&
(hdr->loadflags & BIG_KERNEL_FLAG);
/* Determine load address *///决定保护模式内核uImage的加载地址
if (big_image)
*load_addressp = BZIMAGE_LOAD_ADDR;
else
*load_addressp = ZIMAGE_LOAD_ADDR;
=>memset(setup_base, 0, sizeof(*setup_base));//初始化setup_base
setup_base->hdr = params->hdr;
if (bootproto >= 0x0204)
kernel_size = hdr->syssize * 16;
else
kernel_size -= setup_size;
if (bootproto == 0x0100) {
/*
* A very old kernel MUST have its real-mode code
* loaded at 0x90000
*/
if ((ulong)setup_base != 0x90000) {
/* Copy the real-mode kernel *///老内核需要实模式的setup.bin引导
memmove((void *)0x90000, setup_base, setup_size);
/* Copy the command line */
memmove((void *)0x99000,
(u8 *)setup_base + COMMAND_LINE_OFFSET,
COMMAND_LINE_SIZE);
/* Relocated */
setup_base = (struct boot_params *)0x90000;
}
/* It is recommended to clear memory up to the 32K mark */
memset((u8 *)0x90000 + setup_size, 0,
SETUP_MAX_SIZE - setup_size);
}
=>memmove((void *)*load_addressp, image + setup_size, kernel_size);//将保护模式内核拷贝到内存指定地方,保护模式参数作为出参返回
=>return setup_base;//返回实模式地址
如果protocol为0x100才加载setup.bin。所以猜测uboot在保护模式下直接启动linux的保护模式uImage,而跳过了内核的实模式部分。
而grub则不一定,估计是实模式加载setup.bin然后跳转。
将来有机会仔细研究。
linux boot 学习
https://blog.csdn.net/zeflove/article/details/7565269
慢慢欣赏linux x86 bootloader加载kernel的策略相关推荐
- 全志A10/A20 Bootloader加载过程分析
原文 : http://blog.csdn.net/allen6268198/article/details/12905425 从这里开始:http://linux-sunxi.org/Bootabl ...
- 【转】全志A10/A20 Bootloader加载过程分析
原文 : http://blog.csdn.net/allen6268198/article/details/12905425 从这里开始:http://linux-sunxi.org/Bootabl ...
- 转 A10/A20 Bootloader加载过程分析
A10/A20 Bootloader加载过程分析 注:由于全志A10和A20在加载Bootloader过程方面基本一致,下面仅以A20叙述,但同时也适用于A10.另外在不需要区分Cubieboard1 ...
- 转:A10/A20 Bootloader加载过程分析
来自:http://blog.csdn.net/allen6268198/article/details/12905425 A10/A20 Bootloader加载过程分析 注:由于全志A10和A20 ...
- linux内核被加载的过程
现采取的措施是 在loader加载kernel的同时 也加载initial RAM Disk ==initrd 到内存中. initrd在一般命名为/boot/initrd(14M) 其作用是挂载内存 ...
- linux ipv6模块,有关Linux ipv6模块加载失败的问题
有关Linux ipv6模块加载失败的问题 同事一个SUSE11sp3环境配置ipv6地址失败,提示不支持IPv6,请求帮助,第一反应是应该ipv6相关内核模块没有加载. 主要检查内容: ipv6地址 ...
- Linux重新读写分区的命令,用partprobe、blockdev、hdparm、partx命令在Linux中重新加载分区表...
本文介绍Linux操作系统重新加载分区表的方法:使用partprobe.blockdev.hdparm.partx命令. 背景 作为Linux管理员,你可以在一天内多次执行磁盘分区任务.大多数情况下, ...
- Linux环境变量加载的研究
我们经常遇到在linux执行某条命令时出现xxx文件没找到的问题.很多情况都不是库没有安装,而是环境变量的错误. 但是,我明明是设置了环境变量啊.所以,我对此进行了试验. 我们登录linux有很多种, ...
- linux path环境变量检索目录,Linux下动态链接库加载路径及搜索路径问题
引子 近日,服务器迁移后,偷懒未重新编译nginx的,直接./nginx启动,结果遇到如下问题: "error while loading shared libraries" 这是 ...
最新文章
- html5 响应式布局
- 【桌面虚拟化】之四设计方法
- pandas read_csv 出现中文乱码
- 【计组实验】P4 Verilog多周期处理器微系统 MIPS指令集
- (一)Neo4j在Centos7虚拟机上的安装
- 字符串p型编码(信息学奥赛一本通-T1145)
- C++:获取图片文件信息-图片名称、类型、像素宽高
- Django多域名配置之Django-hosts插件的使用
- Angualr8 ViewChild报错
- prim算法_最小生成树(Kruskal和Prim算法)
- python共享内存mmap_python - IPC在单独的Docker容器中的Python脚本之间共享内存 - 堆栈内存溢出...
- 卧槽!真可恶,竟然有人贩卖儿童软色情表情包,网友:...
- 众多时间时钟Flash动画素材一键即可获取
- WebS WebStorm WebStorm WebS官方版下载
- 游戏测试主要工作及主要流程
- matlab 日期加小时数_将EXCEL 中的日期 时间 导入到MATLAB坐标轴中
- ffmpeg滤镜专题2-高斯模糊
- 副高 职称计算机 上海,高级职称评定
- 不积跬步无以至千里,不积小流无以成江海
- UE4流关卡与无缝地图切换总结