---
# System prepended metadata

title: Qemu review
tags: [Qemu]

---

---
title: Qemu review
tags: Qemu
lang: zh_tw
---

# Qemu review
[TOC]

## Intro
這篇主要回顧一下 firmadyne 產生的 `run.sh` 裡面使用的 qemu 指令，實際上的參數，確實有補理解了一些漏掉的事情

- 這一篇能解答為何會出現以下 Error
    ```
    [ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
    ```


## 指令
這裡隨便拿一個 arm 架構的 `run.sh` 使用的 qemu 指令，紀錄一下我理解的 `-nographic` 之前的參數

```
QEMU_AUDIO_DRV=none ${QEMU} \
    -m 256 -M ${QEMU_MACHINE} -kernel ${KERNEL} \
    -drive if=none,file=${IMAGE},format=raw,id=rootfs \
    -device virtio-blk-device,drive=rootfs \
    -append "root=${QEMU_ROOTFS} \
             console=ttyS0 \
             nandsim.parts=64,64,64,64,64,64,64,64,64,64 \
             rdinit=/firmadyne/preInit.sh \
             rw \
             debug \
             ignore_loglevel \
             print-fatal-signals=1 \
             user_debug=31 \
             firmadyne.syscall=0" \
    -nographic \
    -device virtio-net-device,netdev=net0 \
    -netdev socket,id=net0,listen=:2000 \
    -device virtio-net-device,netdev=net1 \
    -netdev socket,id=net1,listen=:2001 \
    -device virtio-net-device,netdev=net2 \
    -netdev socket,id=net2,listen=:2002 \
    -device virtio-net-device,netdev=net3 \
    -netdev socket,id=net3,listen=:2003 | tee ${WORK_DIR}/qemu.final.serial.log
```
### QEMU_AUDIO_DRV=none
TBD.

### -m
`-m 256` 設定 ram 大小 256M

### -M
`-M "virt"` 參考[註2](https://wiki.qemu.org/Documentation/Platforms/ARM#Generic_ARM_system_emulation_with_the_virt_machine)
> If you don't care about reproducing the idiosyncrasies of a particular bit of hardware, such as small amount of RAM, no PCI or other hard disk, etc., and just want to run Linux, the best option is to use:
> `-M "virt"`
> 

### -kernel
參考[註3](https://helpmanual.io/help/qemu-system-arm/)
> bzImage use 'bzImage' as kernel image
> 
設定 kernel

### -drive
這指令還有許多參數
- if
    interface, 可以設定為 ide, scsi 之類的
    問題來了, 設定為 none 真正代表什麼? I don't know
- file
    設定本機上的哪個檔案對應這個 drive
- format
    設定為 raw 就是不會套用任何 header 規則處理，這邊可能還需要多補充
- id
    任意取名，指令 `-device` 的參數 `drive` 會用到

### -device
一樣也可以設定一些參數

- virtio-blk-device
這邊我不太確定，但如此設定應該就是會在虛擬機中產生 /dev/vda1，至於 vda 是什麼可以參考[註4](https://codeday.me/bug/20181113/367788.html)

- drive
實際對應到什麼裝置，這邊輸入 rootfs 就是剛剛取名為 rootfs 的 device，對應到主機上的 `${IMAGE}`

### -append
傳遞給 kernel 的參數，想多了解參數們可以參考[註5](https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt)

以下列出目前我有看的參數

- root
    整個 filesystem 的 root, 這邊 `${QEMU_ROOTFS}` 是 `/dev/vda1`，就是剛剛 `-device virtio-blk-device...` 創造出來的 VirtIO device，若這邊把 `${QEMU_ROOTFS}` 改成 `/dev/sda1` 則會
    ![](https://i.imgur.com/7bEX61n.jpg)

- rdinit
    參考[註5](https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt)
    > Run specified binary instead of /init from the ramdisk,
    > used for early userspace startup. See initrd.
            
    `rdinit=/firmadyne/preInit.sh` 這行讓 `/firmadyne/preInit.sh` 能夠被執行，但是確切是何時執行(kernel 執行完後執行? 在 /sbin/init 前還是後執行?) 還要追 code
    
- firmadyne.syscall=0
    這是 firmadyne 自行添加的 kernel 選項，可以看他們的 README
    | Parameter | Default   | Values | Description |
    | --------- | --------- | ------ | ----------- |
    | devfs     | 1 (on)    | 0, 1   | Create stubs in devfs and emulate behavior |
    | execute   | 1 (on)    | 0 - 5  | Counter to execute `/firmadyne/console` after 4th `execve()` syscall (requires syscall hooks), 0 to disable |
    | reboot    | 1 (on)    | 0, 1   | Attempt to emulate system reboot by re-executing `/sbin/init` |
    | procfs    | 1 (on)    | 0, 1   | Create stubs in procfs and emulate behavior |
    | syscall   | 255 (all) | 0 - 16 | Output log bitmask for hooking system calls using the `kprobe` framework, 0 to disable |

- rw
    參考[註5-2](http://man7.org/linux/man-pages/man7/bootparam.7.html)
    > The 'rw' option tells the kernel to mount the root filesystem read/write.  This is the default.
    > 
    filesystem 可讀寫
    
### -net
在進行 ARM-X 的實驗中, 其中一個設定檔如下
```
qemu-system-arm -M vexpress-a9 \
-m 256M \
-kernel /host/armx/Tenda_AC15/kernel/zImage-2.6.39.4-vexpress \
-drive file=/host/armx/hostfs/hostfs.ext2,if=sd,format=raw \
-append "pty.legacy_count=16 console=ttyAMA0 rw root=/dev/mmcblk0 rootwait rootfstype=ext2   ARMX=Tenda_AC15" \
-net nic,model=lan9118 \
-net tap,ifname=tap0,script=no,downscript=no 
-nographic -gdb tcp::6666
```

可以用 `-net nic,model=help` 列出能用的 model

能用的 model 會與目前的 machine type (例如此例的 `vexpress-a9`) 對應

# Reference

## Qemu documentation
1. https://wiki.gentoo.org/wiki/QEMU/Options
2. https://wiki.qemu.org/Documentation/Platforms/ARM
3. https://helpmanual.io/help/qemu-system-arm/

## Virtualization
4. [虚拟化 – /dev/vda和/ dev/sda之间的区别是什么](https://codeday.me/bug/20181113/367788.html)

## Kernel 相關
5. [Kernel Parameters](https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt)

5-2. [bootparam](http://man7.org/linux/man-pages/man7/bootparam.7.html)

6. [Kernel devices](https://www.kernel.org/doc/Documentation/admin-guide/devices.txt)

## Firamdyne Kernel Readme
7. [Firamdyne ARM Kernel v3.10.96](https://github.com/firmadyne/kernel-v3.10/blob/firmadyne-v3.10.96/README.md#introduction)
8. [Firamdyne ARM Kernel v4.1](https://github.com/firmadyne/kernel-v4.1/blob/e0f7940fcf0bd34fc9163ec32d10076dbeb4a96e/README.md#introduction)

## Others
9. https://www.slideshare.net/saumilshah/arm-iot-firmware-emulation-workshop

