原创 制作USB启动Linux系统的过程★★★★★★★

2011-6-14 21:08 1390 12 12 分类: MCU/ 嵌入式
 
 
我制作USB启动Linux系统的过程

我一直想做一个在U盘自己启动和运行的Linux系统,近来花费了一些功夫,初步做出了一个基本可以运行的这样的系统,现在记录一下,一是供自己以后参考;二是与大家共同学习和切磋;三是为本论坛增加一点人气。

一 我的制作环境:
先说硬件环境,只说与本系统制作可能有关系的:我的U盘是一个比较早期的朗科64M盘,主板芯片时一个Sis的早期版本。我想现在新的主板和新的U盘应该会比我的硬件具备更好的硬件兼容性。我先把Bios里面的启动介质设置为USB-HDD,另外三种USB启动方式在我这次中都不能成功启动。
我的软件环境,或者说我的操作系统是Sarge。

二 我的基本思路
诚然要做一个比较完善的实用系统,最好是在已经有的Linux发行版的基础上进行加工和修改来做,比如说在Morphix、Knoppix、DSL等基础上进行再加工,但是我做这个系统的主要目的时满足自己的好奇心,另外也是作为学习的一种方式,所以我从更基础的步骤开始,包括自己编译内核、自己制作根目录系统、自己进行各种配置等---当然最好能从自己编写所有源码的最基础开始,但那是不可能的。

三 制作过程:
1 编译内核
具体的编译过程就不说了,资料随处可见,在这里关键是注意为了使U盘启动时能找到自己的根目录系统,需要打一个补丁。
关于这个补丁的详情可见:
http://www.lammerts.org/software/kernelpatches/
由于这个补丁是针对内核2.4.22的,所以我专门下载了2.4.22版本的源码---我不知道这个补丁是否对2.4内核的其他版本起作用,而针对2.6内核的补丁又有不同。
然后,解压—打补丁—编译—得到bzImage,不提。

2 制作根目录系统
制作根目录系统的文章也很多,我这里就不重复,值得注意的是:
i)由于现在使用的时U盘,空间较软盘宽松得多,所以我没有使用busybox,而是从我自己工作的Sarge系统的bin sbin lib等目录中直接拷贝需要的东西。
ii)一般我们都使用initrd来分两个阶段启动Linux,由initrd来挂载U盘上的文件系统。不知道为什么,我不喜欢这种方式。经过实验证明,直接由grub或是syslinux来指定根目录文件系统是可行的。
iii)现在我的根目录里面几乎没有什么配置文件,连inittab fstab等都没有,以后再改进吧。

3 处理U盘
首先要使用fdisk cfdisk对U盘分区,我把我的U盘划分为两个区,第一个10M的boot区,第二个是50M的root区,注意将boot分区设置为可启动的---在DOS下叫激活吧。
然后要建立文件系统,因为我对syslinux比对grub熟悉一些,所以我使用:
#mkdosfs /dev/sda1
#mke2fs /dev/sda2
将boot分区建立为FAT文件系统而将root分区建立为ext2文件系统---用grub应该不用这么麻烦,待我下次再研究如何用grub来加载启动U盘上的内核。

再然后就要这样对U盘进行syslinux处理:
#syslinux /dev/sda

复制相关的文件到U盘,在挂上相应的文件系统之后,把前面编译的内核bzImage复制到sda1,而把自己制作的根文件系统复制到sda2。

最后编写一个syslinux的配置文件并把它复制到sda1里面。(实际上sda1里面只有三个文件,一是内核;一是syslinux系统文件;一是下面的syslinux.cfg)
#nano syslinux.cfg
title myusb
kernel bzImage
root /dev/sda2

制作完成,现在启动电脑就可以顺利进入到我的U盘了---虽然内核在启动的时候还会报告找不到root文件系统,但是折腾了几下之后,它就找到了并顺利执行init,现在电脑上出现了:
init#
表示可以使用U盘Linux系统了。

但是这个系统还做不了什么事情,需要对许多的配置文件进行创建,比如说现在的系统连用nano vi等编辑文件都总报告”error opening terminal”的错误而退出,需要复制原来系统的/etc/terminfo/l/linux文件才能正常运行。
我本来是想制作一个能运行Gcc+Rhide的小型C语言学习系统---就象当年用一张软盘,拷贝上Dos+TurboC 1.0就能到处学习C语言一样,但现在事情看起来复杂得多,现在要安装Gcc就很麻烦,还需要不断的探索。

====================================================================
 
引用:
用grub应该不用这么麻烦,待我下次再研究如何用grub来加载启动U盘上的内核。
See http://www.linuxsir.org/bbs/showthre...=153674&page=3
引用:
但是这个系统还做不了什么事情,需要对许多的配置文件进行创建,比如说现在的系统连用nano vi等编辑文件都总报告”error opening terminal”的错误而退出,需要复制原来系统的/etc/terminfo/l/linux文件才能正常运行。
我本来是想制作一个能运行Gcc+Rhide的小型C语言学习系统---就象当年用一张软盘,拷贝上Dos+TurboC 1.0就能到处学习C语言一样,但现在事情看起来复杂得多,现在要安装Gcc就很麻烦,还需要不断的探索。
I strongly recommend you follow the LFS handbook so that you can have a more in depth understanding on how to build your own Linux.
 
==============================================================
 
用了两天的时候, 终于做出来了,很有成就感哈,呵呵
感谢楼主的支持


但是现在存在一个问题,
#mount /dev/cdrom /mnt/cdrom
总会出现问题,其实mount其他时也是这样的提示:
mount:mounting /dev/cdrom on /mnt/cdrom failed :no such file or directory

而且在#ifconfig时,也没有反应

请楼主指点一下
================================================================
“mount /dev/cdrom /mnt/cdrom”

/mnt/cdrom下有没有cdrom挂载点
=================================================================
引用:
作者: 20000p
“mount /dev/cdrom /mnt/cdrom”

/mnt/cdrom下有没有cdrom挂载点
Then, create one by yourself!

mkdir /mnt/cdrom
 
==================================================================
 
我的内核在启动的时候报告找不到root文件系统,我尝试用 redhat 安装光盘中的dosutils/loadlin.exe

loadlin bzImage root=/dev/sda2 ro

sda2是ext3 格式, 系统内核是2.4.20 编译支持usb ,sisc等
 
=======================================================================
 
我猜可能是DOS的loadlin.exe不能辨认你的U盘
====================================================================
 
不应该是loadlin.exe 的问题吧, 内核已经加载起来了。再内核检测初始化硬件后提示“打开根分区 root=/dev/sda2 失败”
==================================================================
loadlin也许只是加载了bzImage但无法识别U盘(scsi device)上的root filesystem,未知能否用initrd来解决
 
=================================================================
 
 
我用google怎么也搜不到2.6的能用的内核补丁,后来实在无奈,仔细研读了源代码里面的/init/do_mounts.c部分,发现源代码里本来就提供了一个rootdelay参数,可以设定加载根文件系统之前的延时时间,以秒为单位,一般在启动引导程序syslinux,grub,lilo中直接加一个rootdelay=5,肯定就可以了。
后来我在kernel.org上查了一下,好像是在2.6.11-rc2中加入的。
-------------------------------------------------------------------
From: Daniel Drake <dsd@gentoo.org>

Adds a boot parameter which can be used to specify a delay (in seconds)
before the root device is decoded/discovered/mounted.

Example usage for 10 second delay:

rootdelay=10

Useful for usb-storage devices which no longer make their partitions
immediately available, and for other storage devices which require some
"spin-up" time.

Signed-off-by: Daniel Drake <dsd@gentoo.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

25-akpm/Documentation/kernel-parameters.txt | 3 +++
25-akpm/init/do_mounts.c | 15 +++++++++++++++
2 files changed, 18 insertions(+)

diff -puN Documentation/kernel-parameters.txt~configurable-delay-before-mounting-root-device Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~configurable-delay-before-mounting-root-device 2005-01-22 23:33:13.038162280 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt 2005-01-22 23:33:13.043161520 -0800
@@ -1117,6 +1117,9 @@ running once the system is up.

root= [KNL] Root filesystem

+ rootdelay= [KNL] Delay (in seconds) to pause before attempting to
+ mount the root filesystem
+
rootflags= [KNL] Set root filesystem mount option string

rootfstype= [KNL] Set root filesystem type
diff -puN init/do_mounts.c~configurable-delay-before-mounting-root-device init/do_mounts.c
--- 25/init/do_mounts.c~configurable-delay-before-mounting-root-device 2005-01-22 23:33:13.039162128 -0800
+++ 25-akpm/init/do_mounts.c 2005-01-22 23:33:13.044161368 -0800
@@ -6,6 +6,7 @@
#include <linux/suspend.h>
#include <linux/root_dev.h>
#include <linux/security.h>
+#include <linux/delay.h>

#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
@@ -228,8 +229,16 @@ static int __init fs_names_setup(char *s
return 1;
}

+static unsigned int __initdata root_delay;
+static int __init root_delay_setup(char *str)
+{
+ root_delay = simple_strtoul(str, NULL, 0);
+ return 1;
+}
+
__setup("rootflags=", root_data_setup);
__setup("rootfstype=", fs_names_setup);
+__setup("rootdelay=", root_delay_setup);

static void __init get_fs_names(char *page)
{
@@ -387,6 +396,12 @@ void __init prepare_namespace(void)

mount_devfs();

+ if (root_delay) {
+ printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
+ root_delay);
+ ssleep(root_delay);
+ }
+
md_run_setup();

if (saved_root_name[0]) {
======================================================================

果然,2.6.11以后的内核不用对USB设备启动打补丁了,因为内核里已经包含了该功能,
只要在引导内核时给内核传递一个参数rootdelay即可,如下,rootdelay=5 表示等待5秒,我经过测试,OK!
kernel /boot/vmlinuz-2.6.13.4 ro root=/dev/hda3 rootdelay=5 vga=791

=========================================================================

遇到的问题一般有两个:
1. 根分区无法初始化。
可能有两个原因,内核USB驱动没有弄好;或者是U盘初始化没有完成,可以在启动参数中加上rootdelay=6
修改grub启动参数,kernel增加 rootdelay=6,去掉 quiet
2. 找不到或者无法运行init。
initrd和initramfs不同的启动方法需要的init的默认位置不一样,/sbin/init或者/init,可以是脚本,也可以静态或动态编译的程序,一定要注意相关的库文件和程序能够运行。还有就是内核可执行文件类型也要选对。

=========================================================================

文章评论0条评论)

登录后参与讨论
我要评论
0
12
关闭 站长推荐上一条 /2 下一条