in Embedded

Embedded Linux S3C2440 – QEMU and Graphic

Summary

Tested QEMU and Graphic application on Embedded Linux S3C2440.
QEMU is open-source software, can be run on Windows and Linux host, it is software based emulator and instruction set simulator to be used to simulate the embedded processors. QEMU supports the emulation of several target architectures like ARM, PowerPC, x86.

QT for embedded linux is a C++ framework for GUI and application development for embedded device. It can be run on a variety of processors included Embedded Linux. QT provides the standard QT API for embedded devices with a lightweight window system. QT is meant for cross-platform development, the source code can be compiled on x86 platform, run and debug it on the host PC, the same source code for your target platform can be compiled for the target architecture. The application can also be debugged through remote debugging tools, and only the QT-Embedded is installed.

Run a QT Demo on QEMU

All the test will be running on the host and on the instruction set simulator.
The QEMU instruction set simulator qemu-system-arm is installed in /home/iot/qemu-mini2440/qemu/arm-softmmu. The source code is in /home/iot/qemu-mini2440/qemu, this version is dedicated for S3C2440 board. It executes the bootloader u-boot first.

[root@localhost arm-softmmu]# pwd
/home/iot/qemu-mini2440/qemu/arm-softmmu
[root@localhost arm-softmmu]# ls
arm_boot.d     cbus.d         exec.d         ide.d            mini2440.d     omap2.d      op_helper.d     pl031.d        pxa2xx_gpio.o    realview_gic.o  s3c24xx_udc.d     syborg_interrupt.d  tosa.d           vga.d
arm_boot.o     cbus.o         exec.o         ide.o            mini2440.o     omap2.o      op_helper.o     pl031.o        pxa2xx_keypad.d  realview.o      s3c24xx_udc.o     syborg_interrupt.o  tosa.o           vga.o
arm-dis.d      config.h       fpu            integratorcp.d   monitor.d      omap_clk.d   osdep.d         pl050.d        pxa2xx_keypad.o  rtl8139.d       serial.d          syborg_keyboard.d   translate-all.d  virtio-balloon.d
arm-dis.o      config.mak     framebuffer.d  integratorcp.o   monitor.o      omap_clk.o   osdep.o         pl050.o        pxa2xx_lcd.d     rtl8139.o       serial.o          syborg_keyboard.o   translate-all.o  virtio-balloon.o
arm_pic.d      cpu-exec.d     framebuffer.o  isa_mmio.d       mpcore.d       omap_dma.d   palm.d          pl061.d        pxa2xx_lcd.o     s3c2410.d       smc91c111.d       syborg.o            translate.d      virtio-blk.d
arm_pic.o      cpu-exec.o     gdbstub.d      isa_mmio.o       mpcore.o       omap_dma.o   palm.o          pl061.o        pxa2xx_mmci.d    s3c2410_nand.d  smc91c111.o       syborg_pointer.d    translate.o      virtio-blk.o
arm-semi.d     disas.d        gdbstub.o      iwmmxt_helper.d  mst_fpga.d     omap_dss.d   pci.d           pl080.d        pxa2xx_mmci.o    s3c2410_nand.o  soc_dma.d         syborg_pointer.o    tsc210x.d        virtio-console.d
arm-semi.o     disas.o        gdbstub-xml.c  iwmmxt_helper.o  mst_fpga.o     omap_dss.o   pci.o           pl080.o        pxa2xx.o         s3c2410.o       soc_dma.o         syborg_rtc.d        tsc210x.o        virtio-console.o
arm_sysctl.d   dm9000.d       gdbstub-xml.d  libqemu.a        musicpal.d     omap_i2c.d   pcnet.d         pl110.d        pxa2xx_pcmcia.d  s3c2440_nand.d  spitz.d           syborg_rtc.o        tusb6010.d       virtio-net.d
arm_sysctl.o   dm9000.o       gdbstub-xml.o  loader.d         musicpal.o     omap_i2c.o   pcnet.o         pl110.o        pxa2xx_pcmcia.o  s3c2440_nand.o  spitz.o           syborg_serial.d     tusb6010.o       virtio-net.o
arm_timer.d    e1000.d        gumstix.d      loader.o         ne2000.d       omap_lcdc.d  pflash_cfi01.d  pl181.d        pxa2xx_pic.d     s3c24xx_gpio.d  start-qemu        syborg_serial.o     usb-musb.d       vl.d
arm_timer.o    e1000.o        gumstix.o      lsi53c895a.d     ne2000.o       omap_lcdc.o  pflash_cfi01.o  pl181.o        pxa2xx_pic.o     s3c24xx_gpio.o  stellaris.d       syborg_timer.d      usb-musb.o       vl.o
armv7m.d       eepro100.d     helper.d       lsi53c895a.o     neon_helper.d  omap_mmc.d   pflash_cfi02.d  pl190.d        pxa2xx_timer.d   s3c24xx_lcd.d   stellaris_enet.d  syborg_timer.o      usb-ohci.d       wdt_i6300esb.d
armv7m_nvic.d  eepro100.o     helper.o       machine.d        neon_helper.o  omap_mmc.o   pflash_cfi02.o  pl190.o        pxa2xx_timer.o   s3c24xx_lcd.o   stellaris_enet.o  syborg_virtio.d     usb-ohci.o       wdt_i6300esb.o
armv7m_nvic.o  eeprom24c0x.d  host-utils.d   machine.o        nseries.d      omap_sx1.d   pl011.d         pxa2xx.d       qemu-options.h   s3c24xx_mmci.d  stellaris.o       syborg_virtio.o     versatilepb.d    wdt_ib700.d
armv7m.o       eeprom24c0x.o  host-utils.o   mainstone.d      nseries.o      omap_sx1.o   pl011.o         pxa2xx_dma.d   qemu-system-arm  s3c24xx_mmci.o  syborg.d          tc6393xb.d          versatilepb.o    wdt_ib700.o
blizzard.d     esp.d          i386-dis.d     mainstone.o      omap1.d        onenand.d    pl022.d         pxa2xx_dma.o   realview.d       s3c24xx_rtc.d   syborg_fb.d       tc6393xb.o          versatile_pci.d  zaurus.d
blizzard.o     esp.o          i386-dis.o     Makefile         omap1.o        onenand.o    pl022.o         pxa2xx_gpio.d  realview_gic.d   s3c24xx_rtc.o   syborg_fb.o       tcg                 versatile_pci.o  zaurus.o
[root@localhost arm-softmmu]# 

The uImage kernel-uImage is in /home/iot/qemu-mini2440/qemu/mini2440/.

U-boot for S3C2440 source code is in /home/iot/uboot-mini2440/.

QT 4.8.1 is installed in /usr/local/qt. QT demos are installed in /usr/local/qt/demos.

First run the script mini2440_start.sh to start QEMU.

[root@localhost qemu]# pwd
/home/iot/qemu-mini2440/qemu
[root@localhost qemu]# ./mini2440/mini2440_start.sh 
Starting in ./mini2440
/home/iot/qemu-mini2440/qemu/arm-softmmu/qemu-system-arm -M mini2440 -drive file=./mini2440/mini2440_snapshots.img,snapshot=on -serial stdio -kernel /home/iot/qemu-mini2440/qemu/mini2440/kernel-uImage -mtdblock ./mini2440/mini2440_nand.bin -usb -usbdevice mouse -usbdevice keyboard -show-cursor -net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no
S3C: CLK=240 HCLK=240 PCLK=240 UCLK=57                                                                                                                                                                                                       
QEMU: ee24c08_init                                                                                                                                                                                                                           
DM9000: INIT QEMU MAC : 52:54:00:12:34:56                                                                                                                                                                                                    
QEMU mini2440_reset: loaded default u-boot from NAND                                                                                                                                                                                         
QEMU mini2440_reset: loaded override u-boot (size 39800)                                                                                                                                                                                     
QEMU mini2440_reset: loaded /home/iot/qemu-mini2440/qemu/mini2440/kernel-uImage (size 53ce00)                                                                                                                                            
S3C: CLK=240 HCLK=60 PCLK=30 UCLK=57                                                                                                                                                                                                         
S3C: CLK=240 HCLK=60 PCLK=30 UCLK=48                                                                                                                                                                                                         
S3C: CLK=405 HCLK=101 PCLK=50 UCLK=48                                                                                                                                                                                                        


U-Boot 1.3.2-mini2440 (Apr 23 2013 - 14:35:51)                                                                                                                                                                                               

I2C:   ready                                                                                                                                                                                                                                 
DRAM:  64 MB                                                                                                                                                                                                                                 
NOR Flash not found. Use hardware switch and 'flinit'                                                                                                                                                                                        
Flash:  0 kB                                                                                                                                                                                                                                 
NAND:  Bad block table not found for chip 0                                                                                                                                                                                                  
Bad block table not found for chip 0
64 MiB
*** Warning - bad CRC or NAND, using default environment

USB:   S3C2410 USB Deviced
In:    serial
Out:   serial
Err:   serial
MAC: 08:08:11:18:12:27
Hit any key to stop autoboot:  0 
MINI2440 # 

The script mini2440_start.sh is as below,


\#!/bin/bash base=$(dirname $0) echo Starting in $base name_nand="$base/mini2440_nand.bin" name_snapshots="$base/mini2440_snapshots.img" if [ ! -f "$name_nand" ]; then echo $0 : creating NAND empty image : "$name_nand" dd if=/dev/zero of="$name_nand" bs=528 count=131072 fi if [ ! -f "$name_snapshots" ]; then echo $0 : creating empty snapshot image : "$name_snapshots" /home/iot/qemu-mini2440/qemu/qemu-img create "$name_snapshots" 100MB fi #-usbdevice keyboard #-show-cursor #-serial tcp::2222,server #-serial stdio #-monitor telnet::5555,server,nowait cmd="/home/iot/qemu-mini2440/qemu/arm-softmmu/qemu-system-arm \ -M mini2440 $* \ -drive file=$name_snapshots,snapshot=on \ -serial stdio \ -kernel /home/iot/qemu-mini2440/qemu/mini2440/kernel-uImage \ -mtdblock "$name_nand" -usb -usbdevice mouse -usbdevice keyboard\ -show-cursor \ -net nic,vlan=0 \ -net tap,vlan=0,ifname=tap0,script=no" echo $cmd $cmd

Kernel-uImage is a precompiled kernel image in uImage format. It contains the executable of the affine demo and the libraries needed. As above script shows, the kernel option is -kernel /home/iot/qemu-mini2440/qemu/mini2440/kernel-uImage, it tells QEMU to load the kernel of the simulated machine S3C2440 in the RAM, after S3C2440 boot up and the Bootloader command prompt appeared, can use help command to show all u-boot commands, as below shows.

MINI2440 # help
?       - alias for 'help'
autoscr - run script from memory
base    - print or set address offset
bdinfo  - print Board Info structure
boot    - boot default, i.e., run 'bootcmd'
bootd   - boot default, i.e., run 'bootcmd'
bootm   - boot application image from memory
bootp   - boot image via network using BootP/TFTP protocol
chpart  - change active partition
cmp     - memory compare
coninfo - print console devices and information
cp      - memory copy
crc32   - checksum calculation
date    - get/set/reset date & time
dhcp    - invoke DHCP client to obtain IP/boot params
dynenv  - dynamically placed (NAND) environment
dynpart - dynamically calculate partition table based on BBT
echo    - echo args to console
erase   - erase FLASH memory
ext2load- load binary file from a Ext2 filesystem
ext2ls  - list files in a directory (default /)
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls   - list files in a directory (default /)
flinfo  - print FLASH memory information
flinit  - Initialize/probe NOR flash memory
fsinfo  - print information about filesystems
fsload  - load binary file from a filesystem image
go      - start application at address 'addr'
help    - print online help
icrc32  - checksum calculation
iloop   - infinite loop on address range
imd     - i2c memory display
iminfo  - print header information for application image
imls    - list all images found in flash
imm     - i2c memory modify (auto-incrementing)
imw     - memory write (fill)
imxtract- extract a part of a multi-image
in      - read data from an IO port
inm     - memory modify (constant address)
iprobe  - probe to discover valid I2C chip addresses
itest   - return true/false on integer compare
loadb   - load binary file over serial line (kermit mode)
loads   - load S-Record file over serial line
loady   - load binary file over serial line (ymodem mode)
loop    - infinite loop on address range
ls      - list files in a directory (default /)
md      - memory display
mm      - memory modify (auto-incrementing)
mmcinit - init mmc card
mtdparts- define flash/nand partitions
mtest   - simple RAM test
mw      - memory write (fill)
nand    - NAND sub-system
nboot   - boot from NAND device
nfs     - boot image via network using NFS protocol
nm      - memory modify (constant address)
out     - write datum to IO port
ping    - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
rarpboot- boot image via network using RARP/TFTP protocol
reginfo - print register information
reset   - Perform RESET of the CPU
run     - run commands in an environment variable
s3c24xx - SoC  specific commands
saveenv - save environment variables to persistent storage
saves   - save S-Record file over serial line
setenv  - set environment variables
sleep   - delay execution for some time
tftpboot- boot image via network using TFTP protocol
usb     - USB sub-system
usbboot - boot from USB device
version - print monitor version
MINI2440 # 

Before jump to kernel, we nee do key in Linux command line to set the simulated screen size. U-boot will pass it to kernel.

MINI2440 # setenv bootargs console=ttySAC0,115200 init=/init mini2440=1tb

As above shows, mini2440=1tb, 1 means the screen is 7′ LCD 800*480, t means touch screen and b means back light.

Use command bootm to jump to kernel, then key in root to log in.

MINI2440 # bootm
## Booting kernel from Legacy Image at 32000000 ...
   Image Name:   
   Created:      2019-05-31   6:54:22 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    5491848 Bytes =  5.2 MB
   Load Address: 30008000
   Entry Point:  30008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
s3c_timers_write: Bad register 0x40
s3c_uart_write: Bad register 0x2c
Booting Linux on physical CPU 0x0
Linux version 3.8.7-FriendlyARM (root@localhost.localdomain) (gcc version 4.7.2 (Buildroot 2013.02) ) #11 Wed Aug 16 15:51:19 SGT 2017
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: MINI2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: root=/dev/mtdblock3 rootfstype=jffs2 console=ttySAC0,115200
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
__ex_table already sorted, skipping sort
Memory: 64MB = 64MB total
Memory: 52796k/52796k available, 12740k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xc4800000 - 0xff000000   ( 936 MB)
    lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .text : 0xc0008000 - 0xc0427ee4   (4224 kB)
      .init : 0xc0428000 - 0xc0b61a04   (7399 kB)
      .data : 0xc0b62000 - 0xc0b9d988   ( 239 kB)
       .bss : 0xc0b9d988 - 0xc0bd9948   ( 240 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:85
irq: clearing subpending status 00000002
sched_clock: 32 bits at 200 Hz, resolution 5000000ns, wraps every 4294967291ms
Console: colour dummy device 80x30
Calibrating delay loop... 67.99 BogoMIPS (lpj=169984)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0x30307150 - 0x3030718c
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
MINI2440: Option string mini2440=0tb
MINI2440: 't' ignored, touchscreen not compiled in
MINI2440: LCD [0:240x320] 1:800x480 2:1024x768 3:320x240
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C244X: Clock Support, DVS off
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Linux video capture interface: v2.00
NET: Registered protocol family 2
TCP established hash table entries: 512 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 512 bind 512)
TCP: reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
NetWinder Floating Point Emulator V0.97 (double precision)
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
msgmni has been set to 103
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Console: switching to colour frame buffer device 30x20
s3c2410-lcd s3c2410-lcd: fb0: s3c2410fb frame buffer device
s3c2440-uart.0: ttySAC0 at MMIO 0x50000000 (irq = 70) is a S3C2440
console [ttySAC0] enabled
s3c2440-uart.1: ttySAC1 at MMIO 0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: ttySAC2 at MMIO 0x50008000 (irq = 76) is a S3C2440
brd: module loaded
loop: module loaded
Loading iSCSI transport class v2.0-870.
s3c24xx-nand s3c2440-nand: Tacls=1, 9ns Twrph0=3 29ns, Twrph1=2 19ns
s3c24xx-nand s3c2440-nand: NAND soft ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit), 64MiB, page size: 512, OOB size: 16
Creating 4 MTD partitions on "nand":
0x000000000000-0x000000040000 : "u-boot"
0x000000040000-0x000000060000 : "u-boot-env"
0x000000060000-0x000000560000 : "kernel"
0x000000560000-0x000004000000 : "root"
dm9000 Ethernet Driver, V1.31
dm9000_probe Set bwscon and bankcon4
eth0: dm9000e at c48bc300,c48be304 IRQ 51 MAC: 08:08:11:18:12:27 (chip)
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver rndis_host
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
mousedev: PS/2 mouse device common for all mice
s3c-rtc s3c2410-rtc: rtc disabled, re-enabling
s3c-rtc s3c2410-rtc: rtc core: registered s3c as rtc0
oprofile: no performance counters
oprofile: using timer interrupt.
TCP: cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
Key type dns_resolver registered
console [netcon0] enabled
netconsole: network logging started
s3c-rtc s3c2410-rtc: setting system clock to 2019-06-05 11:21:34 UTC (1559733694)
s3c_uart_write: Bad register 0x2c
Freeing init memory: 7396K
s3c_uart_write: Bad register 0x2c
s3c_uart_write: Bad register 0x2c
starting pid 440, tty '': '/etc/init.d/rcS'
* Mounting /proc...
* Mounting /dev...
* Mounting /sys...
* Mounting /dev/pts...
* Mounting /dev/shm...
* Starting system loggers...
* Creating devices...
* Configuring loopback interface...
* Setting hostname...
eth0 up
dm9000_mii_read: Bad register 0x1b
dm9000 dm9000 eth0: link up, 10Mbps, half-duplex, lpa 0x0400
s3c_uart_write: Bad register 0x2c
starting pid 456, tty '': '/usr/sbin/telnetd -l /bin/login'
s3c_uart_write: Bad register 0x2c
starting pid 457, tty '': '-/bin/login'
mini2440 login: root
-sh: can't access tty; job control turned off
[root@mini2440 /root]# 

Change to directory /usr/bin, run a script qtsetting.sh to set environment variables for QT.

[root@mini2440 /root]# cd /usr/bin/
[root@mini2440 bin]# ls
affine               less                 opreport
awk                  logger               oprofiled
cut                  logname              pstree
dirname              lsusb                pwdx
env                  op-check-perfevents  qtsetting.sh
expr                 opannotate           sv
fold                 oparchive            tftp
free                 opcontrol            time
ftpget               openvt               top
ftpput               operf                tr
gdbserver            opgprof              uptime
id                   ophelp               wget
install              opimport             which
ldd                  opjitconv
[root@mini2440 bin]# cat qtsetting.sh 
#!/bin/sh
export QWS_DISPLAY=LinuxFB:mmWidth=95:mmHeight=155
export QWS_KEYBOARD=USB:/dev/input/event0
export QWS_MOUSE_PROTO=IntelliMouse:/dev/input/mice
export QWS_SIZE=800*480
[root@mini2440 bin]# source qtsetting.sh 
[root@mini2440 bin]# 

The little penguin appears on the emulated LCD.
Little penguin

Run the affine demo at the back ground,

[root@mini2440 bin]# ./affine -qws &
[root@mini2440 bin]# 

On the simulated screen of S3C2440, the animation of affine is as below, you can use the mouse on the screen to click the buttons and bars. To exit the mouse from the screen, press Ctrl+Alt. To terminate the QEMU, press Ctrl + C.

affine demo

The affine demo is in the QT demo directory on the host,

[root@localhost affine]# ls
affine  affine.pro  affine.qrc  bg1.jpg  main.cpp  xform.cpp  xform.h  xform.html
[root@localhost affine]# pwd
/usr/local/qt/demos/affine
[root@localhost affine]# 

It was compiled into zImage then convert into kernel-uImage through shell script create_rootfs_bash.sh,

cp -P /usr/local/qt/lib/libQtGui* usr/local/qt/lib
cp -P /usr/local/qt/lib/libQtNetwork* usr/local/qt/lib
cp -P /usr/local/qt/lib/libQtCore* usr/local/qt/lib
cp -rdP /usr/local/qt/lib/fonts usr/local/qt/lib
cp /usr/local/qt/demos/affine/affine usr/bin

Convert the kernel image to uImage format

Use the script generateKerneluImage.sh to convert the kernel image to uImage format and put into /home/iot/qemu-mini2440/qemu/mini2440/,

#!/bin/sh
./mkimage -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d mini2440/linux-3.8.7/arch/arm/boot/zImage qemu-mini2440/qemu/mini2440/kernel-uImage

The script converts the file mini2440/linux-3.8.7/arch/arm/boot/zImage to kernel-uImage, as below help information shows, the parameter -A specifies architecture. -O specifies OS. -a specifies load address. -e specifies execute address. -d specified the input file.

[root@localhost]# ./mkimage -h
Usage: ./mkimage -l image
          -l ==> list image header information
       ./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch'
          -O ==> set operating system to 'os'
          -T ==> set image type to 'type'
          -C ==> set compression type 'comp'
          -a ==> set load address to 'addr' (hex)
          -e ==> set entry point to 'ep' (hex)
          -n ==> set image name to 'name'
          -d ==> use image data from 'datafile'
          -x ==> set XIP (execute in place)
       ./mkimage [-D dtc_options] -f fit-image.its fit-image

QEMU Networking

QEMU allows the guest OS to communicate with the host OS via Ethernet. We need to create a bridge between them. The script qemu-ifup is used to achieve this. The content of qemu-ifup is as below. The script takes two parameters. The first parameter is the name of tap device, e.g. tap0. The second parameter is the device name of the Ethernet interface, such as eth0, p3p1 or em1, etc.

#!/bin/sh
#
# script to bring up the tun device in QEMU in bridged mode
# first parameter is name of tap device (e.g. tap0)
#
# some constants specific to the local host - change to suit your host
#
ETH0IP=192.168.0.10
GATEWAY=192.168.0.1
BROADCAST=192.168.0.255   #determined by subnet range used
#
# First take eth0 down, then bring it up with IP 0.0.0.0
#
#sudo /sbin/ifdown eth0
sudo /sbin/ifdown $2
#
#sudo /sbin/ifconfig eth0 0.0.0.0 promisc up
sudo /sbin/ifconfig $2 0.0.0.0 promisc up
#
# Bring up the tap device (name specified as first argument, by QEMU)
#
sudo /usr/sbin/openvpn --mktun --dev $1 --user `id -un`
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
#
# create the bridge between eth0 and the tap device
#
sudo /usr/sbin/brctl addbr br0 
#sudo /usr/sbin/brctl addif br0 eth0
sudo /usr/sbin/brctl addif br0 $2
sudo /usr/sbin/brctl addif br0 $1
#
# only a single bridge so loops are not possible, turn off spanning tree protocol
#
sudo /usr/sbin/brctl stp br0 off 
#
# Bring up the bridge with ETH0IP and add the default route if you are using static IP
#
/sbin/ifconfig br0 $ETH0IP netmask 255.255.255.0 broadcast $BROADCAST
/sbin/route add default gw $GATEWAY
#
#
# stop firewall, if you dont you cannot run virtual OS for public services as outside can't connect to it.
#
systemctl stop firewalld.service

The current Ethernet interface configuration is as below, we will use Ethernet interface eth0 as the bridge setting.

[root@localhost ~]# ifconfig
eth0: flags=4163<up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fefc:6596  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:fc:65:96  txqueuelen 1000  (Ethernet)
        RX packets 31  bytes 3339 (3.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 39  bytes 3862 (3.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.101  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::a00:27ff:fece:b1b2  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:ce:b1:b2  txqueuelen 1000  (Ethernet)
        RX packets 1718  bytes 166886 (162.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1878  bytes 297301 (290.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth2: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.1  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::a00:27ff:fe5e:4788  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:5e:47:88  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 578 (578.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73</up><up ,LOOPBACK,RUNNING>  mtu 16436
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 22  bytes 1690 (1.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 22  bytes 1690 (1.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099<up ,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether c6:fb:dc:85:32:8f  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# 

Use the above script qemu-ifup to setup the bridge, the second parameter is the host Ethernet port device name.

[root@localhost ~]# ./qemu-ifup tap0 eth0
Wed Jun  5 23:07:30 2019 TUN/TAP device tap0 opened
Wed Jun  5 23:07:30 2019 Persist state set to: ON
[root@localhost ~]# 

Check the result as below,

[root@localhost ~]# ifconfig
br0: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.10  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::a00:27ff:fefc:6596  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:fc:65:96  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6  bytes 468 (468.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4419</up><up ,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        inet6 fe80::a00:27ff:fefc:6596  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:fc:65:96  txqueuelen 1000  (Ethernet)
        RX packets 31  bytes 3339 (3.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 45  bytes 4330 (4.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.101  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::a00:27ff:fece:b1b2  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:ce:b1:b2  txqueuelen 1000  (Ethernet)
        RX packets 1723  bytes 168429 (164.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1882  bytes 298105 (291.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth2: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.1  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::a00:27ff:fe5e:4788  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:5e:47:88  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 578 (578.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73</up><up ,LOOPBACK,RUNNING>  mtu 16436
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 22  bytes 1690 (1.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 22  bytes 1690 (1.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tap0: flags=4355<up ,BROADCAST,PROMISC,MULTICAST>  mtu 1500
        ether ea:48:eb:db:58:53  txqueuelen 100  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099</up><up ,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether c6:fb:dc:85:32:8f  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# 

Test the connection by ping the target simulated S3C2440.
First startup,

[root@localhost qemu]# ./mini2440/mini2440_start.sh
...(omit..load the kernel image into RAM of the emulated S3C2440 board)
MINI2440 # setenv bootargs console=ttySAC0,115200 init=/init mini2440=1tb
MINI2440 # bootm
...(omit..from u-boot jump to the kernel image in RAM)
mini2440 login: root
-sh: can't access tty; job control turned off
[root@mini2440 /root]# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:08:11:18:12:27  
          inet addr:192.168.0.11  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:51 Base address:0x2300 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

From host ping to simulated S3C2440 linux, it was failed,

[root@localhost ~]# ping 192.168.0.11
PING 192.168.0.11 (192.168.0.11) 56(84) bytes of data.
From 192.168.0.1 icmp_seq=1 Destination Host Unreachable

Noticed that the eth2 also has 192.168.0.1 address, it is the same network segment as the bridge, it may confuse the host network connection, ifdown eth2 and ping again, it is successful now after the change.

[root@localhost ~]# ifdown eth2
[root@localhost ~]# ping 192.168.0.11
PING 192.168.0.11 (192.168.0.11) 56(84) bytes of data.
64 bytes from 192.168.0.11: icmp_seq=1 ttl=64 time=7.56 ms
64 bytes from 192.168.0.11: icmp_seq=2 ttl=64 time=0.296 ms
^C
--- 192.168.0.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.296/3.929/7.563/3.634 ms
[root@localhost ~]# ifconfig
br0: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.10  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::a00:27ff:fefc:6596  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:fc:65:96  txqueuelen 0  (Ethernet)
        RX packets 4  bytes 224 (224.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10  bytes 748 (748.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4419</up><up ,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        inet6 fe80::a00:27ff:fefc:6596  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:fc:65:96  txqueuelen 1000  (Ethernet)
        RX packets 31  bytes 3339 (3.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 46  bytes 4390 (4.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.101  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::a00:27ff:fece:b1b2  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:ce:b1:b2  txqueuelen 1000  (Ethernet)
        RX packets 1726  bytes 169322 (165.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1884  bytes 298507 (291.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth2: flags=4163</up><up ,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::a00:27ff:fe5e:4788  prefixlen 64  scopeid 0x20<link />
        ether 08:00:27:5e:47:88  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13  bytes 938 (938.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73</up><up ,LOOPBACK,RUNNING>  mtu 16436
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 29  bytes 2474 (2.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29  bytes 2474 (2.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tap0: flags=4419<up ,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        inet6 fe80::e848:ebff:fedb:5853  prefixlen 64  scopeid 0x20<link />
        ether ea:48:eb:db:58:53  txqueuelen 100  (Ethernet)
        RX packets 4  bytes 280 (280.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10  bytes 748 (748.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099</up><up ,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether c6:fb:dc:85:32:8f  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# 

Now you can try NFS, tftp and telnet operations.

Test on Telnet,

[root@localhost ~]# telnet 192.168.0.11
Trying 192.168.0.11...
Connected to 192.168.0.11.
Escape character is '^]'.

mini2440 login: root
[root@mini2440 /root]# 

Test on TFTP:

[root@mini2440 /root]# tftp -g -r thread_demo_RR_max_min 192.168.0.10
thread_demo_RR_max_m 100% |********************************************************************************************************************************************************************************************| 10576   0:00:00 ETA
[root@mini2440 /root]# ls
thread_demo_RR_max_min
[root@mini2440 /root]# 

Test on NFS,

[root@mini2440 /root]# mount -t nfs 192.168.0.10:/home /mnt -otcp, -o nolock
[root@mini2440 /root]# mount
rootfs on / type rootfs (rw)
/proc on /proc type proc (rw,relatime)
mdev on /dev type tmpfs (rw,relatime)
none on /sys type sysfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600)
none on /dev/shm type tmpfs (rw,relatime)
192.168.0.10:/home on /mnt type nfs (rw,relatime,vers=3,rsize=131072,wsize=131072,namlen=255,hard,nolock,proto=tcp,port=2049,timeo=70,retrans=3,sec=sys,local_lock=all,addr=192.168.0.10)
[root@mini2440 /root]# 

You can also do the gdb debugging, kernel debugging and profiling by using QEMU.

A script qemu-ifdown is used to delete the bridge and restore the Ethernet interface device configuration, it takes the same parameters of qemu-ifup. The script content is as below,

#!/bin/sh                                                                                                                                                                                                                                    
#                                                                                                                                                                                                                                            
# Script to bring down and delete bridge br0 when QEMU exits                                                                                                                                                                                 
# parameter $1: name of tap such as tap0                                                                                                                                                                                                     
# parameter $2: name of the ethernet inferface, such as eth0, p3p1                                                                                                                                                                           
# Bring down eth0 and br0                                                                                                                                                                                                                    
#                                                                                                                                                                                                                                            
#/sbin/ifdown eth0                                                                                                                                                                                                                           
/sbin/ifdown $2                                                                                                                                                                                                                              
/sbin/ifdown br0                                                                                                                                                                                                                             
/sbin/ifconfig br0 down                                                                                                                                                                                                                      
#                                                                                                                                                                                                                                            
#                                                                                                                                                                                                                                            
# Delete the bridge                                                                                                                                                                                                                          
#                                                                                                                                                                                                                                            
sudo /usr/sbin/brctl delbr br0                                                                                                                                                                                                               
#                                                                                                                                                                                                                                            
# bring up eth0 in "normal" mode                                                                                                                                                                                                             
#                                                                                                                                                                                                                                            
#/sbin/ifconfig eth0 -promisc                                                                                                                                                                                                                
/sbin/ifconfig $2 -promisc                                                                                                                                                                                                                   
#/sbin/ifup eth0                                                                                                                                                                                                                             
/sbin/ifup $2                                                                                                                                                                                                                                
#
# delete the tap device
#
/usr/sbin/openvpn --rmtun --dev $1
#
# start firewall again
#
systemctl start firewalld.service

Booting via TFTP

Earlier QEMU test loaded the kernel uImage into RAM when boot the emulated S3C2440 board. U-boot also support other booting approaches such as TFTP boot and BOOTP. Below test was booting the kernel via TFTP.

Copy the kernel-uImage into directory /var/lib/tftpboot tftp folder.

[root@localhost qemu]# cp /home/iot/qemu-mini2440/qemu/mini2440/kernel-uImage /var/lib/tftpboot/

Start QEMU, in the u-boot command line, set the IP address as below,

[root@localhost qemu]# ./mini2440/mini2440_start.sh
...(omit...)
MINI2440 # setenv ipaddr 192.168.0.11

Tell u-boot to retrieve uImage named as kernel-uImage from address 192.168.0.10 and loaded in RAM address 0x30800000.

MINI2440 # tftpboot 0x30800000 192.168.0.10:kernel-uImage                                       
dm9000 i/o: 0x20000300, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 08:08:11:18:12:27
TFTP from server 192.168.0.10; our IP address is 192.168.0.11
Filename 'kernel-uImage'.
Load address: 0x30800000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##################################################
done
Bytes transferred = 5491912 (53ccc8 hex)

After u-boot received the file and put it at address 0x30800000, then u-boot will find from the uImage header that it should relocate the kernel image. Now we can jump to the kernel image by using bootm command,

MINI2440 # bootm
...omit(start up linux...)
mini2440 login: root
-sh: can't access tty; job control turned off
[root@mini2440 /root]# 
[root@mini2440 /root]# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:08:11:18:12:27  
          inet addr:192.168.0.11  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:332 (332.0 B)  TX bytes:280 (280.0 B)
          Interrupt:51 Base address:0x2300 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

[root@mini2440 /root]# 

Reference

Embedded Linux S3C2440 environment setup
Embedded Linux S3C2440 Environment Startup
Embedded Linux S3C2440 Build and Boot an Image
Embedded Linux S3C2440 Application Development and Debugging
Embedded Linux S3C2440 Networking
Embedded Linux S3C2440 – Kernel Module
Embedded Linux S3C2440 – Kernel Debugging
Embedded Linux S3C2440 – Multi-thread Scheduling
Embedded Linux S3C2440 Profiling
QEMU Wiki
Qt (software) Wiki