Build và chạy một bản Linux đơn giản trên QEMU ARM

Thấy có bạn nói về Linux nên làm post hóng cao thủ.:))

Bài này sẽ làm một ví dụ để chỉ ra sự liên quan giữa các thành phần của một hệ thống Linux thông qua việc build, chạy Kernel trên board vexpress-a9 được mô phỏng bằng QEMU.

Đó là Kernel, Root file system, Init Program.


1. "Chém" chút về quá trình khởi động của Linux

  • Về cơ bản, quá trình khởi động Linux có 2 giai đoạn.
    Giai đoạn đầu là load kernel lên RAM và chạy bởi phần mềm bootloader.
    Giai đoạn thứ hai là kernel sẽ phát hiện thiết bị, rồi mount hệ thống file root.
    Nơi mà các chứa các ứng dụng phía user-space sẽ được chạy sau đó, và trên đó ít nhất cũng phải có chương trình tên là init program hay PID = 1.
    Không có hệ thống file root này thì kernel cũng vô dụng.
    Hình như bất cứ bản Linux nào, dù lớn, dù bé đều thì tối thiểu phải có 2 giai đoạn ở trên.

  • Để chạy Linux trên các board sử dụng chip ARM, ta cần 2 điều kiện
    Thứ nhất, board được kernel hỗ trợ. (tức là nó chứa phần BSP - Board Support Package thì phải?!?)
    Thứ hai, ta phải có hoặc tạo file device tree chứa thông tin các device mà kernel có thể truy cập được khi kernel chạy.
    Sau đây là gõ lệnh.

2. Chuẩn bị môi trường

Ubuntu 16.04 LTS hoặc các môi trường Linux tương tự và tương đối mới
Giả sử ta sẽ thao tác một thư mục tên có tên qemu_arm_test trong HOME

3. Tải về

  • Linux kernel bản stable mới nhất

Vào trang http://www.kernel.org/, rồi tải bản stable mới nhất
Hoặc lấy link rồi sử dụng wget như sau:

$cd qemu_arm_test
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.10.8.tar.xz
  • Busybox bản stable mới nhất

Vào trang http://busybox.net, rồi tải bản stable mới nhất
Hoặc lấy link rồi sử dụng wget như sau:

$cd qemu_arm_test
$ wget http://busybox.net/downloads/busybox-1.26.2.tar.bz2

4. Cài đặt môi trường

  • Cài đặt cross-compiler chạy trên Linux, build code cho ARM

Có rất nhiều loại Toolchain dành cho ARM mà chúng ta có thể cài trên Linux.
Danh sách có thể tham khảo tại đây.
Ở đây chúng ta sẽ sử dụng Linaro (ARM) vì cài đặt khá dễ dàng trên Ubuntu thông qua repo của nó.
Câu lệnh như sau:

$sudo add-apt-repository ppa:linaro-maintainers/toolchain
$sudo apt-get install gcc-arm-linux-gnueabi

Sau khi cài đặt xong, ta có thể thấy các command sau:
arm-linux-gnueabi-gcc, arm-none-eabi-gcc

  • Cài đặt Qemu ARM để mô phỏng board vexpress-a9

QEMU thì quá nổi tiếng rồi, và cũng được viết bởi một siêu nhân cũng quá nổi tiếng.
Chương trình phần cứng mã nguồn mở.

$sudo apt-get install qemu qemu-system-arm

Để khởi động thử board vexpress-a9

$qemu-system-arm -M vexpress-a9 -m 512

Nếu lên được một màn hình windows rồi tắt là ok, chứng tỏ các tham số là tạm ổn.
Chỉ là máy chưa biết chạy cái gì thôi.

5. Biên dịch

Ta sẽ tiến hành build kernel rồi Busybox

5.1 Biên dịch Linux Kernel

  • Giải nén kernel
$unxz linux-4.10.8.tar.xz
$tar -xvf linux-4.10.8.tar
  • Cấu hình và build kernel bằng Toolchain ta đã cài ở trên
$cd linux-4.10.8
$make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig
$make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all

Khi khi quá trình build kết thúc, bạn sẽ thấy nhân được tạo trong
đường dẫn linux-4.10.8/arch/arm/boot/zImage.
Chốc nữa ta sẽ khởi động bằng zImage đó.

5.2 Biên dịch Busybox

  • Giải nén

    $bzip2 -d -k busybox-1.26.2.tar.bz2
    
  • Cấu hình và build Busybox bằng Toolchain đã cài ở trên
    Sử dụng cấu hình mặc định

$cd busybox-1.26.2
$make ARCH=arm CROSS_COMPLIE=arm-linux-gnueabi- defconfig

Chúng ta sẽ không sử dụng shared library (tức là không có run-time loader-linker)
vì thế phải sửa cấu hình build của Busybox để chỉ hỗ trợ build static thôi.
Load lên là chạy luôn.

$make ARCH=arm CROSS_COMPLIE=arm-linux-gnueabi- menuconfig

Chú ý là, có thể phải cài thư viện libcurses-dev thì mới chạy được
giao diện cấu hình.
Sau đó chỉnh sửa ở đường dẫn sau:
Busybox Settings > Build Options > Build BusyBox as a static binary (no shared libs)

Sau đó build Busybox bằng câu lệnh sau:

$make ARCH=arm CROSS_COMPLIE=arm-linux-gnueabi-  install

Kết quả build sẽ nằm ở thư mục _install,
Nội dung thư mục này sẽ như sau:

_install$ ls
bin linuxrc sbin usr

6. Tạo file system chứa Busybox

Như đã nói ở trên, ta cần một file system để chứa ứng dụng phía user-space.
Ít nhất phải có init program, là chương trình đầu tiên mà kernel sẽ chạy.
Process của chương trình này luôn là 1, và cha của mọi tiến trình trong Linux.

Vậy, một file system tối thiệu liệu cần những gì.
Thật may mắn, kết quả sau khi build Busybox đã cho ta gần như đủ 1 file system rồi.
Tuy nhiên, ta cần một vài file cấu hình cho init proram, cấu hình mount hệ thống nữa.

Đường dẫn của init program trong file system có thể được chỉ định trong tham
số khởi động kernel.
Nếu không được chỉ định thì có vẻ nó sẽ tìm theo thức tự sau:
Theo source code từ kernel/init/main.c:990

if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))

Busybox là một tập các công cụ chuẩn trên Unix được viết lại đơn giản hơn, nó cũng implement một init program nằm ở /sbin/init (lucky) luôn. Ta có thể xem trong nội dung thư mục _install* ở trên.

Trong bài này, ta sẽ tham khảo cấu hình trong ví dụ tạo file system dành cho đĩa mềm (floppy disk) mà BusyBox cung cấp.

Cụ thể sẽ làm như sau:
Tại thư mục source của Busybox:

$cd examples/bootfloopy
$ls
bootfloppy.txt etc mkrootfs.sh quickstart.txt
display.txt mkdevs.sh mksyslinux.sh syslinux.cfg

Ta thấy có một thư mục tên etc ở trên.

Giờ, ta sẽ sử dụng thư mục etc và thư mục _install (được tạo khi build Busybox)
để tạo file system.

Đầu tiên, tạo thư mục chứa nội dung toàn bộ file system, sau đó copy vào thôi.

$mkdir rootfs_content
$cp -fR busybox-1.26.2/examples/etc rootfs_content
$cp -fR busybox-1.26.2/_install/* rootfs_content
$ls rootfs_content
bin etc linuxrc sbin usr

Ta sẽ tạo thêm một vài thư mục phụ có thể cần cho kernel chạy nữa:

$cd rootfs_content
$mkdir dev home mnt proc root sys tmp var

Cuối cùng ta có cấu trúc thư mục như sau:

├── bin
├── dev
├── etc
├── home
├── linuxrc -> bin/busybox
├── mnt
├── proc
├── root
├── sbin
├── sys
├── tmp
├── usr
└── var

Ta cần sửa một chút file cấu hình của init program.
Nó nằm ở /etc/inittab, sửa nội dung thành như sau:
Vì file cấu hình mặc định chỉ định /dev/tty2 là console. Trong trường hợp này để chọn mặc định vậy.

::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::ctrlaltdel:/bin/umount -a -r

Giờ ta sẽ tạo file system từ thư mục rootfs_content ở trên.
Đầu tiên, tạo một file system ext3 trống:

$dd if=/dev/zero of=BusyBoxRootFS.ext3 bs=1M count=32
$mkfs.ext3 BusyBoxRootFS.ext3

Sau đó, mount file system vừa tạo trong file BusyBoxRootFS.ext3
vào để tạo nội dung cho nó (nhớ phải có tham số -o nha), copy nội dung đã chuẩn bị sang.

$sudo mount -t ext3 BusyBoxRootFS.ext3 tmpfs/ -o loop
$cp -fR rootfs_content/* tmpfs/

Cuối cùng là umount nó:

$umount tmpfs

Giờ file hệ thống chứa các ứng dụng user-space nằm trong file system bên trong file BusyboxRootFS.ext3 rồi.

7. Chạy

Ta kiểm tra lại những thứ đã làm trước khi chạy
qemu-system-arm : đã cài
kernel : đã build
file system : đã tạo

Giờ ta sẽ chạy, câu lệnh như sau:

$qemu-system-arm -M vexpress-a9 \
-dtb linux-4.10.8/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-kernel linux-4.10.8/arch/arm/boot/zImage \
-append "root=/dev/mmcblk0 console=ttyAMA0" \
-sd BusyBoxRootFS.ext3 \
-serial stdio

QEMU

Trên cửa sổ dòng lệnh sẽ hiện ra terminal của máy Qemu:

Cùng với một màn hình có chim cánh cụt:

Ta kiểm tra máy đang chạy bằng:

#uname -a
#cat /proc/cpuinfo

Sẽ thấy máy chạy là ARM, phiên bản kernel là 4.10.8 vừa build
và một số thông tin khó hiểu khác.:))

8. Tham khảo

  1. Learning from you blog - https://learningfromyoublog.wordpress.com/
  2. Free Embedded - https://learningfromyoublog.wordpress.com/
  3. Busybox - https://www.busybox.net/
  4. BusyBox simplifies embedded Linux systems - https://www.ibm.com/developerworks/library/l-busybox/
  5. Linux stable - https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/
  6. QEMU System ARM - https://qemu.weilnetz.de/doc/qemu-doc.html#ARM-System-emulator
  7. Lazytrick - http://lazytrick.wordpress.com =)))
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Phùng Văn Tú

13 bài viết.
66 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
22 8
Chúng ta thường nghe nhiều đến Unicode, UTF8, UTF16, hay ShiftJS. Trong bài này chỉ xin làm rõ những khái niệm này để khi gặp phải vấn đề về Chars...
Phùng Văn Tú viết hơn 2 năm trước
22 8
White
18 6
4 thành phần của Embedded Linux Ta biết rằng Linux chạy ở khắp nơi từ siêu máy tính, máy chủ, máy để bàn (máy xách tay), điện thoại (android)...ch...
Phùng Văn Tú viết 9 tháng trước
18 6
White
17 2
Gần đây tôi có dịp đụng vào CMake, nên có tìm hiểu một chút về nó. Hy vọng có ích cho anh em. Nó cung cấp tính năng sinh ra Makefile một cách hiệu...
Phùng Văn Tú viết hơn 2 năm trước
17 2
Bài viết liên quan
White
1 0
sudo du sh
t viết gần 2 năm trước
1 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
13 bài viết.
66 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!