[玩法/技巧] 讨论Buffalo LS-WVL刷群晖或者威联通的NAS系统,HDMI改造等。 |
看了你的帖子,我分别下了一下buffalo和群晖的ROM发现2者的启动镜像是有区别的.buffalo的启动镜像是uimage文件,群晖的是zimage文件。二者是有区别的。
引用一下别人的东西 zImage 和uImage 都是生成的可执行内核镜像文件 2者在u-boot中启动的方式分别是 go addr 与 bootm addr 来实现启动过程的 即对于zImage是通过 go 来进行引导 而uImage是通过bootm来进行引导的 zImage 和 uImage 2者的关系 是 uImage 是zImage通过mkimage (u--boot下面tools下的工具)来生成的 结果是后者比前者在头部多了64个byte,这多余的64个byte是用来通知给u-boot用的;将相关信息告知u-boot; 这样做的结果在u-boot引导内核时存在2个地址:loadaddress 和entry address 2者的差值刚好是0x40(64byte)的大小 这样在使用bootm loadaddress 时u-boot会根据相应的loadaddress进行调整,有2中情况; 1)、当loadaddress与mkimage时传送的一致时: 那么在加载 ldr pc,entry address时,会选择mkinage 时的entry地址;即pc=loadaddress + 4;然后由pc来控制流程跳转倒ram中去执行; 2)、当loadaddress与mkimage时传送的不一致时: 那么,u-bbot会进行地址比较后,将当前的loadaddress减去64byte后,将真正的内核映像(去掉64byte头部的内核)拷贝倒预先制定的loadaddress,然后直接从这个loadaddress来引导内核运行; 总结,那么上面2中情况实际区别呢?其实就是最终代码执行时,如果地址与mkinage时指定的不符,那么u-boot将进行去头后,拷贝内核代码,直接执行;而如果不处理,则会将 loadaddress+0x40来执行内核; 通过tftp服务来下载 zImage或者uImage; loadb 在tftp不成功的情况下使用 串口来下载内核 希望不要用这个方法 cp【.b\.w\.l】 完成 内存之间 内存向flash之间进行拷贝 最后可以设置 bootcmd 环境变量可以实现 u-boot自动引导内核启动 至于文件系统的2中方式:ramdisk 以及nfs 推荐开发者使用nfs 方便修改; 当使用ramdisk时, #gunzip k9.img.gz //解压缩 #mount –o loop k9.img /mnt/new_disk //挂载 #umount /mnt/new_disk //卸载 #gzip –c –v9 k9.img > k9.img.gz //压缩生成最终的文件系统 也就是说在进行启动镜像的flash拷贝时应该注意一下拷贝的起始位置。不知道我想的对不对,请指正。 |
|
转帖点东西
前言 最近几个月将Linux Kernel的大概研究了一下,下面需要进行深入详细的分析。主要将以S3C2440的一块开发板为硬件实体。大概包括如下内容: 1 bootloader分析,以uboot为主,结合具体开发板的情况。我的目标是解释清楚uboot的工作原理(说实话,分析过程中不太想被硬件绑架,但是需要以一个实际的例子 来做分析) 2 kernel部分,这就很多内容了。打算从kernel启动的流程开始分析。 3 除kernel本身外,还有很多的知识,例如ld的输入script分析等,这里会一起介绍。 kernel启动流程概要 一:内核Image的组成 1 ES(Embed System)启动的时候,CPU加电,执行的第一条语句是Bootloader,这个非常类似PC机上的BIOS。BL将内核加载后,控制器移交给LK 2 LK执行的第一条语句是什么?vmlinux是单体的内核表示。根据前面说的内核编译连接知识,第一条语句是head.S中(历史原因,MD,有很多文件都叫head.S) 我们需要重新分析一下内核(这里就是zImage了)的组成,(方法很简单,研究make的执行过程,通过make V=1 zImage可以得到几乎全部信息) vmlinux,这个是未压缩、未strip的内核模块,ELF结构 Image:二进制、未压缩、但是strip后的内核 head.o:ARM相关的,由BL将控制权转交给它。即前面提到的head.S生成 pigg.gz:Image文件的gzip压缩 piggy.o:由piggy.S生成,这个S文件通过include Bin方式将Image包含进来。piggy的意思就是背负、肩扛。很形象不是? misc.o:从上面看,涉及到一些解压方面的内容,而misc提供一些辅助函数 vmlinux:悲催.....这个文件是head+pigg+misc构成的vmlinux。名字一样不是?真的很混淆! zImage:再由上面这个vmlinux压缩而来 图1很好得展示了这个过程。 图1 内核的构成 3 piggy的故事 piggy.S很有意思,建立了一个section,并且有一个标志来指示piggy.gz的边界。 piggy对应的是一个叫bootstrap的image,注意,Bootstrap和Bootloader不一样,它是在BL之后的一段代码,用来 解压kernel,设置内存等作用。也可以叫second stage boot。 4 Bootloadre和BootstrapLoader BL和BSL的区别是什么? BL只是初始化硬件,不依赖linux,不处理linux BSL在BL后执行,依赖linux,因为要解压linux。另外一个重要点就是BSL需要为LINUX的运行建立环境 BSL的工作包括: head.O:初始化CPU等工作 misc.O:解压,重定位(例如将kernel移动到另外一个位置上) decompress_kernel 其他工作 init/main.c:start_kernel 启动调用图见图2. 图2 启动调用流程图 下面来分析这个启动流程 1 kernel中的head.o分析:尽量保持CPU系列的通用,例如arm的CPU等初始化都在做。但是具体板子(例如CPU+其他硬件)怎么初始化?这就是由mach目录中的初始化函数做到的。所以,kernel初始化分为:generic CPU初始化+具体板子的初始化。head.o初始化后,跳转到main.o的start_kernel,继续后面的流程 2 start_kernel:(init/main.c):start_kernel的转移由head.O做的,不过代码一般包含在更通用的head_common.S中 以后想做kernel的分析,就从main开始吧. start_kernel做了什么事情呢? 刚才只是初始化了cpu相关的,而具体和板子相关的由start_arch执行 3 kernel 参数分析:kernel command line。注意,这个参数是由BL传递给kernel的,不过这个参数又是谁设置的呢?又存在什么地方呢?这个line放在一个global的地方, 另外,kernel如何处理这些参数呢?有一个比较好的办法,__set_up宏,将一些参数和对应的函数指针存在一个特殊的section中,然后循环调用这个section中的函数。(和驱动module中的很像)。定义在init.h中。关于一些特殊参数的取值,在arch/arm/kernel/vmlinux.lds.S中定义。(以后得去看看ld的manual了)__set_up这个宏还有一个flags比如early,表示处理阶段是否在early-stage做。标志有__init的section最终占用的内存会被抛弃.. 4 子系统初始化:包括中断、等。?section嵌套section? 5 kernel_init进程:start_kernel最后会fork一个kernel_init进程,而原执行进程变成idle进程了.. 6 用户空间的init进程:由kernel_init进程最终通过execve init完成 7 参考文献。ELP这本书给的参考文献都巨强.. |
上篇我们知道,kernel初始化后将启动init进程,那么这个进程将干些什么呢?除此之外,kernel还需要做些什么事情呢?(想想文件系统、根存储设备是在什么时候初始化的呢?)
先从文件系统初始化说起。以前一直不明白,有了kernel为何还需要一个文件系统?经过反复琢磨,明白一个道理,kernel加载到内存后,kernel运行起来是没有问题的,但是如果没有Root FS,就好像PC上没有硬盘.....。另外,Linux中很多虚拟文件系统(proc,sys,dev等)都是挂靠在RootFS中的,所以RootFS在Linux中更加关键(必要条件简直就是)。(kernel中的FS是另外一个庞大的部分) 一 根文件系统 1 FHS:File system Hierachy Standard:Linux上文件系统布局的标准,例如 usr目录大概是干吗的,tmp目录大概是干嘛的。有空可以瞧瞧....其实使用LINUX OS多了,自然就理解了。 2 常用的文件夹布局:其实就是ES上普遍的文件目录: bin;dev;etc;home;lib;sbin;tmp;usr;var; 二 Post Boot 这里讲的是execve init之前的事情,因为源码中: run_init_process("/usr/bin/init"):这个时候已经有FS的布局了,也就是init程序本身必须放在一个FS中。 三 init init进程很重要,不过android上的init进程的工作流程比较简单。这里介绍非Android上的init。一般它读取的配置文件是/etc/inittab中(ubuntu上似乎没有这个文件了,以后得找个FCore的系统看看)。 另外,这里还有一个叫run level的概念。见图1. 图1 run level Run level说白了就是将系统运行状态分成几个级别,例如shutdown的时候init需要执行一些操作,reboot的时候需要执行一些操作。 这里关于Init的东西就不介绍了,很多关于linux系统配置的知识都有涉及。(确实比android的init要复杂多了) 四 Initial RAM Disk LK在早期初始化的过程中,需要mount一个FS,目前有新旧两种方法: old方法就是使用initial ram disk,也叫initrd new方法就是使用iniramfs 这两个东西非常常见,咱们要好好研究下。 4.1 initrd 这个功能需要配置kernel的编译选项。 ARM支持将前面的initrd和vmlinux打包到一个image中。实际上只有ARM架构支持。(内核编译的时候要选择这一项)。讲了这么多,那么到底怎么用呢? initrd也是一个image。由bootloader启动的时候,或者bootloader下载到某个地方 bootloader把initrd的地址告诉内核。内核启动时候把这个image解压并挂载 另外一种办法,编译的时候将initrd和kernel放到一个image中,这种方法只有ARM架构支持。使用这种办法话,建议用initramfs。注意,android中使用的就是一个kernel+initramfs的单一image。也就是第二种办法 (这里有很多细节问题,以后我们分析源码再来搞懂它) BL启动内核的时候,需要给LK传递参数,即告诉LK这个initrd在什么位置...很简单不是? KL如何使用这个initrd呢? KL先根据参数指定的initrd地址,将这个image拷贝到内存中,然后解压,并挂载为/ 找到这个disk中的linuxrc文件,然后执行里边的语句《====这给了我们定制化自己ES的好计划 处理完linuxrc后,KL unmount这个initrd,并加载真正的root device(看到没,这个initrd就是做些初始化的工作,但是你也可以不umount这个initrd。)这里的处理稍有差异。如果BL在参数中指明root=/dev/ram0,(代码中可见到这些语句),那么KL就不会执行linuxrc,并且也不会umount initrd。也就是这个initrd就是最终的根文件系统了。 那么如何制作这个Initrd呢? 其实就是一个gzip打包的文件夹.... (这部分代码在do_mounts.c中的prepare_namespace函数中) 4.2 initramfs (详细说明:参考kernel/documentations/filesystems/ramfs-rootfs-initramfs.txt) kernel默认支持这个initramfs,所以编译的时候,会整一个default的initramfs放到内核中。initramfs是一个cpio的打包文件。我特意查了下cpio的info。一般用法就是:读取一个目录下所有文件的信息及其所有文件的内容(可能是直接read数据到一个buffer中),然后把这些信息写到一个文件中。说白了,可能就是一个序列化的工具。然后LK用同样的方法就可以反序列化,恢复原来目录中的内容了。 前面说,LK编译的时候默认会有一个简单的initramfs目录结构。这个结构由kernel/scripts/gen_initramfs_list.sh脚本生成。这个脚本很简单: dir /dev 0755 0 0 nod /dev/console/ 0600 0 0 c 5 1 dir /root 0700 0 0 执行的时候,前面加上mk...就生成一个目录了,然后用cpio打包,生成iniramfs,最后由LK解包并挂载 (具体内容,参考ramfs-rootfs-initramfs.txt) 如何制作自己的initramfs呢? 搞一个文件夹吧,可仿照PC机器上linux的文件结构。也可以把busybox放上去。 find testramfs -depth -print | cpio -ov > testramfs.cpio cpio的输入是文件名,输出通过>定向到testramfs.cpio。大家可以试试。 解压的话,cpio -ivd < testramfs.cpio。这样就能还原testramfs文件夹中的内容了。 cpio:-o表示output,-v表示打印一些verbose信息,-i表示input,-d表示建立整个文件夹结构。没有-d的话,会出问题。 不过有了kernel编译的支持,我们不用自己调用cpio了,在编译选项中有一个INITRAMFS_SOURCE,把它指向目标文件夹,编译的时候自然会生成这个initramfs了。 参考文献: 这些参考文献中,最重要的是最后一个,ols2k-9.ps,下载并处理后得到一个pdf,实际上一篇论文。主要介绍了 Linux启动的一些问题。 再三解释一下,为什么需要init ram disk。FS一般安装在存储介质上,而读取这些存储介质需要驱动。内核启动的时候如果把这些驱动都加载的话,会非常麻烦,即使你把驱动静态编译到内核中,也不是一个完美的解决办法。所以。先整一个简单的,基于内存的FS,这样初始化工作都可以顺利进行。最后,等驱动都加载完后,再把实际存储上的FS挂载上来。这里要明白一点,没有一个FS的话,LK是没法正常工作的。 五 U-Boot 全名为Das U-Boot,是一个使用非常广泛的Bootloader。以后会专门撰文介绍UB。这里简单说两个点: UB的代码结构,先从CPU的start.S开始,这里会根据不同的CPU进行初始化,大部分代码都不需要我们修改 再是Board的启动,这个和具体的板子有关。现在改名叫lowlevel_init.S了。 (最难的部分在于各个设备的初始化了,需要结合开发板的datasheet来做) 这里列出以下参考书: 其中,关于SDRAM.pdf,网址已经移到了:http://www.maxwell.com/products/ ... /INTRO_TO_SDRAM.PDF 各位看官可以下载看看。 |
来顶一下,希望能有更多高手注意此贴。
buffalo的硬件不弱,软件确实与群晖qnap之类的有很大差距,若能互刷固件,那将是一个飞跃。 PS,现在已经有破解版的群晖固件跑在其他系统上,buffalo的硬件与群辉qnap的基本相同,应该有很大机会搞掂的,加油! |
完全支持楼主的折腾精神。这样的话Buffalo就无敌了。现在用QVL,四位的。一星期就搞定许多功能了,现在手机控制PT下载。
|
今天乱试了一下,发现buffalo的启动应该是有个独立的启动盘,NAS通电后先加载启动盘然后加载硬盘。所以这个启动盘是很重要的,群晖固件里有用的应该是2个文件rd.bin和zImage这2个文件时启动盘必须的,但是好像还要有boot文件,这个是固件里缺少的,不是哪位能把群晖DS212的启动盘给镜像共享出来啊
|