由於看到老外作arm模擬器在avr單片機上跑linux啓動bash(花6小時),感受本身也要試試,要是能在個人Huluboard(和UNO配置同樣,328p)上跑linux我該多高興啊,但無論是否成功,能學到是最好
因而先從kernel抓起,找準一個之前編譯的內核,啓動ubuntu,沒錯,uImage,就你了。php
root@ubuntu :~/kernel/linux-sunxi-sunxi-3.4/output#
html
hexdump -C uImage -n 64
linux
00000000 27 05 19 56 7f 91 23 3a 51 a1 53 0b 00 3f dd 28 |'..V..#:Q.S..?.(|
ios
00000010 40 00 80 00 40 00 80 00 83 e5 d5 e1 05 02 02 00 |@... @...........|
shell
00000020 4c 69 6e 75 78 2d 33 2e 34 2e 34 33 00 00 00 00 |Linux-3.4.43....|
ubuntu
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
bash
00000040less
複製代碼electron
uImage的前64個字節是文件頭,後面是zImage
咱們能夠試試:ide
root@ubuntu :~/kernel/linux-sunxi-sunxi-3.4/output# hexdump -C uImage -n 70
00000000 27 05 19 56 7f 91 23 3a 51 a1 53 0b 00 3f dd 28 |'..V..#:Q.S..?.(|
00000010 40 00 80 00 40 00 80 00 83 e5 d5 e1 05 02 02 00 |@... @...........|
00000020 4c 69 6e 75 78 2d 33 2e 34 2e 34 33 00 00 00 00 |Linux-3.4.43....|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 a0 e1 00 00 |......|
00000046
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# hexdump -C zImage -n 6
00000000 00 00 a0 e1 00 00 |......|
00000006
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output#
複製代碼
你們應該看出來了吧?uImage(如下可能簡稱u)後面的6個字節和zImage(同理可能簡稱)的前6字節一致,也就是說,要從uImage裏提取zImage,一個dd命令便可,dd if=uImage of=zImage bs=1 seek=64,不知道對不對……
好吧,研究kernel,看u-boot的code比較合適,由於u-boot是啓動kernel的
u-boot下:
include/image.h
跳過一些code,來啦!
系統代碼,CPU代碼,映像格式,壓縮格式
/*
* Operating System Codes
*/
#define IH_OS_INVALID 0 /* Invalid OS */
#define IH_OS_OPENBSD 1 /* OpenBSD */
#define IH_OS_NETBSD 2 /* NetBSD */
#define IH_OS_FREEBSD 3 /* FreeBSD */
#define IH_OS_4_4BSD 4 /* 4.4BSD */
#define IH_OS_LINUX 5 /* Linux */
#define IH_OS_SVR4 6 /* SVR4 */
#define IH_OS_ESIX 7 /* Esix */
#define IH_OS_SOLARIS 8 /* Solaris */
#define IH_OS_IRIX 9 /* Irix */
#define IH_OS_SCO 10 /* SCO */
#define IH_OS_DELL 11 /* Dell */
#define IH_OS_NCR 12 /* NCR */
#define IH_OS_LYNXOS 13 /* LynxOS */
#define IH_OS_VXWORKS 14 /* VxWorks */
#define IH_OS_PSOS 15 /* pSOS */
#define IH_OS_QNX 16 /* QNX */
#define IH_OS_U_BOOT 17 /* Firmware */
#define IH_OS_RTEMS 18 /* RTEMS */
#define IH_OS_ARTOS 19 /* ARTOS */
#define IH_OS_UNITY 20 /* Unity OS */
#define IH_OS_INTEGRITY 21 /* INTEGRITY */
#define IH_OS_OSE 22 /* OSE */
#define IH_OS_PLAN9 23 /* Plan 9 */
/*
* CPU Architecture Codes (supported by Linux)
*/
#define IH_ARCH_INVALID 0 /* Invalid CPU */
#define IH_ARCH_ALPHA 1 /* Alpha */
#define IH_ARCH_ARM 2 /* ARM */
#define IH_ARCH_I386 3 /* Intel x86 */
#define IH_ARCH_IA64 4 /* IA64 */
#define IH_ARCH_MIPS 5 /* MIPS */
#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */
#define IH_ARCH_PPC 7 /* PowerPC */
#define IH_ARCH_S390 8 /* IBM S390 */
#define IH_ARCH_SH 9 /* SuperH */
#define IH_ARCH_SPARC 10 /* Sparc */
#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */
#define IH_ARCH_M68K 12 /* M68K */
#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */
#define IH_ARCH_NIOS2 15 /* Nios-II */
#define IH_ARCH_BLACKFIN 16 /* Blackfin */
#define IH_ARCH_AVR32 17 /* AVR32 */
#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */
#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */
#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */
#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */
/*
* Image Types
*
* "Standalone Programs" are directly runnable in the environment
* provided by U-Boot; it is expected that (if they behave
* well) you can continue to work in U-Boot after return from
* the Standalone Program.
* "OS Kernel Images" are usually images of some Embedded OS which
* will take over control completely. Usually these programs
* will install their own set of exception handlers, device
* drivers, set up the MMU, etc. - this means, that you cannot
* expect to re-enter U-Boot except by resetting the CPU.
* "RAMDisk Images" are more or less just data blocks, and their
* parameters (address, size) are passed to an OS kernel that is
* being started.
* "Multi-File Images" contain several images, typically an OS
* (Linux) kernel image and one or more data images like
* RAMDisks. This construct is useful for instance when you want
* to boot over the network using BOOTP etc., where the boot
* server provides just a single image file, but you want to get
* for instance an OS kernel and a RAMDisk image.
*
* "Multi-File Images" start with a list of image sizes, each
* image size (in bytes) specified by an "uint32_t" in network
* byte order. This list is terminated by an "(uint32_t)0".
* Immediately after the terminating 0 follow the images, one by
* one, all aligned on "uint32_t" boundaries (size rounded up to
* a multiple of 4 bytes - except for the last file).
*
* "Firmware Images" are binary images containing firmware (like
* U-Boot or FPGA images) which usually will be programmed to
* flash memory.
*
* "Script files" are command sequences that will be executed by
* U-Boot's command interpreter; this feature is especially
* useful when you configure U-Boot to use a real shell (hush)
* as command interpreter (=> Shell Scripts).
*/
#define IH_TYPE_INVALID 0 /* Invalid Image */
#define IH_TYPE_STANDALONE 1 /* Standalone Program */
#define IH_TYPE_KERNEL 2 /* OS Kernel Image */
#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */
#define IH_TYPE_MULTI 4 /* Multi-File Image */
#define IH_TYPE_FIRMWARE 5 /* Firmware Image */
#define IH_TYPE_SCRIPT 6 /* Script file */
#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */
#define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */
#define IH_TYPE_KWBIMAGE 9 /* Kirkwood Boot Image */
#define IH_TYPE_IMXIMAGE 10 /* Freescale IMXBoot Image */
#define IH_TYPE_UBLIMAGE 11 /* Davinci UBL Image */
#define IH_TYPE_OMAPIMAGE 12 /* TI OMAP Config Header Image */
#define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */
#define IH_TYPE_KERNEL_NOLOAD 14 /* OS Kernel Image, can run from any load address */
#define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */
/*
* Compression Types
*/
#define IH_COMP_NONE 0 /* No Compression Used */
#define IH_COMP_GZIP 1 /* gzip Compression Used */
#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */
#define IH_COMP_LZMA 3 /* lzma Compression Used */
#define IH_COMP_LZO 4 /* lzo Compression Used */
複製代碼
還有個define:
#define IH_MAGIC 0x27051956 /* Image Magic Number */
#define IH_NMLEN 32 /* Image Name Length */
複製代碼
接下來是struct:
/*
* Legacy format image header,
* all data in network byte order (aka natural aka bigendian).
*/
typedef struct image_header {
__be32 ih_magic; /* Image Header Magic Number */
__be32 ih_hcrc; /* Image Header CRC Checksum */
__be32 ih_time; /* Image Creation Timestamp */
__be32 ih_size; /* Image Data Size */
__be32 ih_load; /* Data Load Address */
__be32 ih_ep; /* Entry Point Address */
__be32 ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
typedef struct image_info {
ulong start, end; /* start/end of blob */
ulong image_start, image_len; /* start of image within blob, len of image */
ulong load; /* load addr for the image */
uint8_t comp, type, os; /* compression, type of image, os type */
} image_info_t;
複製代碼
通過查詢發現IH_NMLEN = 32,因而判斷後32byte是內核名字,果真
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# hexdump -C uImage -n 32
00000000 27 05 19 56 7f 91 23 3a 51 a1 53 0b 00 3f dd 28 |'..V..#:Q.S..?.(|
00000010 40 00 80 00 40 00 80 00 83 e5 d5 e1 05 02 02 00 |@...@...........|
00000020
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# hexdump -C uImage -n 32 -s 32
00000020 4c 69 6e 75 78 2d 33 2e 34 2e 34 33 00 00 00 00 |Linux-3.4.43....|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output#
複製代碼
前面一直沒想起來,去找各個位置定義,後來忽然想起struct裏的定義和位置有關
你們參考這個:
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# hexdump -C uImage -n 32
00000000 27 05 19 56 7f 91 23 3a 51 a1 53 0b 00 3f dd 28 |'..V..#:Q.S..?.(|
00000010 40 00 80 00 40 00 80 00 83 e5 d5 e1 05 02 02 00 |@...@...........|
00000020
複製代碼
根據struct的定義,發現32字節的末尾有05 02 02 00,它們的定義在上面有貼,uint8_t類型,就是8個bit,一個byte:
05 Linux
02 ARM
02 KERNEL
00 無壓縮
而後繼續往前,__be32類型,32個bit有符號,也就是4個byte,struct裏面寫的是dcrc,看註釋,data的crc,那麼就是zImage的crc,這個嘛,用crc32程序看看(crc32是根據ubuntu提示安裝的,叫libarchive-zip-perl)
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# crc32 zImage
83e5d5e1
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output#
複製代碼
你們往上看,是否是有個83 e5 d5 e1?說明是正確的
再來,兩個address
40 00 80 00 40 00 80 00
兩個都是40 00 80 00
參考這個帖子,裏面有內核引導數據:http://cn.cubieboard.org/forum.php?mod=viewthread&tid=601&extra=
沒錯,對了,就是40008000
再來,00 35 DD 28,是大小,data size,就是zImage的size
先用計算機換成10進制
0x0035dd28=4185384
而後呢:
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output# ls -l zImage
-rwxr-xr-x 1 root root 4185384 Oct 2 17:58 zImage
root@ubuntu:~/kernel/linux-sunxi-sunxi-3.4/output#
複製代碼
啊哈~
接下來,timestamp,時間戳。
51 a1 53 0b=1369527051
網上找個時間戳轉換工具http://tool.chinaz.com/Tools/unixtime.aspx
轉換得2013年5月26日格林尼治標準時間+0800上午8時10分51秒
上面的hcrc個我就以爲有點奇怪了,header裏面調header的CRC?!
附上函數:
int image_check_hcrc(const image_header_t *hdr)
{
ulong hcrc;
ulong len = image_get_header_size();
image_header_t header;
/* Copy header so we can blank CRC field for re-calculation */
memmove(&header, (char *)hdr, image_get_header_size());
image_set_hcrc(&header, 0);
hcrc = crc32(0, (unsigned char *)&header, len);
return (hcrc == image_get_hcrc(hdr));
}
複製代碼
爲啥用memmove,爲啥不直接調用hdr?初學C,感受有點奇怪
看了下:http://blog.csdn.net/ecbtnrt/article/details/6707113
看着一堆include的h文件發暈,你們有啥辦法自動檢測函數位置不?
跳過,繼續,magic魔術,是判斷是否是所需鏡像的
內部定義:
#define IH_MAGIC 0x27051956 /* Image Magic */
複製代碼
正好裏面是27 05 19 56,也正好了
看的文章:
http://atmel.eefocus.com/article ... tml?sort=1098_0_0_0
http://bbs.chinaunix.net/thread-1916502-1-1.html
http://os.chinaunix.net/a2009/1203/1000/000001000100.shtml
http://www.360doc.com/content/09/0727/00/26398_4475381.shtml
http://blog.csdn.net/linweig/article/details/5044978
http://blog.csdn.net/ecbtnrt/article/details/6707113
原文做者:tll
原文連接:http://forum.cubietech.com/forum.php?mod=viewthread&tid=1209&extra=page%3D2