diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2023-06-15 13:04:34 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2023-06-15 13:04:34 +0200 |
commit | d269e28cd97bdd34a1d2278e2b1ed52b9158fc8a (patch) | |
tree | 5a1e690f6568c0cc5cda31c1db10a9b06c6ca9e9 | |
parent | 721bf78ba02d9032a65b4c3c808785f36dcb85c5 (diff) | |
download | i486tcc-linux-d269e28cd97bdd34a1d2278e2b1ed52b9158fc8a.tar.gz i486tcc-linux-d269e28cd97bdd34a1d2278e2b1ed52b9158fc8a.tar.bz2 |
- fixed some documentation
- experimenting with using less and less memory
- added joe editor
-rw-r--r-- | README | 30 | ||||
-rw-r--r-- | configs/linux-config | 6 | ||||
-rw-r--r-- | configs/versions | 3 | ||||
-rw-r--r-- | docs/linuxlink.timesys.com_docs_startup_overview.txt | 193 | ||||
-rwxr-xr-x | local/init | 1 | ||||
-rw-r--r-- | patches/uflbbl-boot-options.patch | 22 | ||||
-rwxr-xr-x | scripts/build.sh | 40 | ||||
-rwxr-xr-x | scripts/create_ramdisk.sh | 7 | ||||
-rwxr-xr-x | scripts/download.sh | 8 | ||||
-rwxr-xr-x | scripts/run_qemu.sh | 2 | ||||
-rwxr-xr-x | scripts/run_qemu_direct.sh | 2 |
11 files changed, 279 insertions, 35 deletions
@@ -183,7 +183,7 @@ The starting point of the Linux kernel configuration is 'make tinyconfig'. "mount: mount: devpts: No such device" - CONFIG_COMPAT_32BIT_TIME - - for 32-bit time parameter as in pselect (this of course maked the + - for 32-bit time parameter as in pselect (this of course made the whole thing non-2038-safe) "vis: mainloop function not implemented", needs 'pselect' @@ -224,6 +224,13 @@ Debugging: CONFIG_FRAME_POINTER=y CONFIG_UNWINDER_FRAME_POINTER=y +Memory optimization: + +- CONFIG_PHYSICAL_START=0x1000000 16M + CONFIG_PHYSICAL_ALIGN=0x2000 8K + CONFIG_RELOCATABLE=n + boot.asm: set ramdisk and linux addresses correctly + TODO FROM HERE: TODO: preemption better for 1 CPU systems, Desktop? @@ -283,8 +290,6 @@ bugs again and a stage2 probably, as it has to run inside the chroot and eventually even inside a qemu emulation). - currently we bundle too many things in the initial ramdisk: - - man pages - - a full tcc compiler with musl/system header files and libraries - all kernel modules (instead of just the essential or/and the ones fitting to the hardware) - kernel modules should remain uncompressed when added to the ramdisk and @@ -325,7 +330,23 @@ bugs when exiting it - If building on x86_64, you need lib32 glibc and gcc-libs for tcc to link a standalone version between stage0 and stage1 - +- does the ramdisk get correctly unmounted? I see a /mnt busy message + when doing the switch_root +- man pages are not compressed on the root partition, mandoc can deal + with compressed pages (as it requires zlib) +- low memory support + low ram: 0 - 011e0000 + -> 011E0000 = 18MB + RAMDISK: [mem 0x00580000-0x0062bfff] + 62BFFF-580000 704511 + -> ramdisk.img is 704152 compressed, where does it get unpacked to + Memory: 12984K/17912K available (1990K kernel code, 446K rwdata, 532K rodata, 204K init, 148K bss, 4928K reserved, 0K cma-reserved) + -> roughly 6 MB of kernel space + Unpacking initramfs... + -> right, where to, or does it live in the cache only? + Freeing initrd memory: 688K + -> is this our ramdisk? we didn't to switch_root yet + missing things -------------- @@ -546,6 +567,7 @@ links - https://z49x2vmq.github.io/2020/12/24/linux-tiny-qemu/ - Boot process - ramdisks + - https://linuxlink.timesys.com/docs/startup_overview - https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html - https://firasuke.github.io/DOTSLASHLINUX/post/booting-the-linux-kernel-without-an-initrd-initramfs/ - https://docs.kernel.org/admin-guide/initrd.html diff --git a/configs/linux-config b/configs/linux-config index defbce0..792f5f5 100644 --- a/configs/linux-config +++ b/configs/linux-config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 6.3.1 Kernel Configuration +# Linux/x86 6.3.2 Kernel Configuration # CONFIG_CC_VERSION_TEXT="gcc (GCC) 13.1.1 20230429" CONFIG_CC_IS_GCC=y @@ -335,9 +335,9 @@ CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set CONFIG_HZ=250 # CONFIG_KEXEC is not set -CONFIG_PHYSICAL_START=0x1000000 +CONFIG_PHYSICAL_START=0x100000 # CONFIG_RELOCATABLE is not set -CONFIG_PHYSICAL_ALIGN=0x200000 +CONFIG_PHYSICAL_ALIGN=0x2000 # CONFIG_COMPAT_VDSO is not set # CONFIG_CMDLINE_BOOL is not set CONFIG_MODIFY_LDT_SYSCALL=y diff --git a/configs/versions b/configs/versions index be6b064..475dce7 100644 --- a/configs/versions +++ b/configs/versions @@ -1,4 +1,4 @@ -LINUX_KERNEL_VERSION="6.3.1" +LINUX_KERNEL_VERSION="6.3.2" TINYCC_VERSION="85b27" MUSL_VERSION="1.2.3" _OKSH_VERSION="7.2" @@ -18,3 +18,4 @@ MANDOC_VERSION="1.14.6" ABASE_VERSION="f2c13" NBD_VERSION="3.25" SAMURAI_VERSION="1.2" +JOE_VERSION="4.6" diff --git a/docs/linuxlink.timesys.com_docs_startup_overview.txt b/docs/linuxlink.timesys.com_docs_startup_overview.txt new file mode 100644 index 0000000..49f721d --- /dev/null +++ b/docs/linuxlink.timesys.com_docs_startup_overview.txt @@ -0,0 +1,193 @@ + [1][squares1.svg] (BUTTON) Toggle navigation + * [2][ll-oneline-inverse.png] + + * + + ____________________ + * [3]Docs + * [4]Vulnerability Notifications + * [5]Create a BSP + * [6]Register + * [7]Log in + + [8]Skip to main content + + [9]Timesys LinuxLink + +The Linux Startup Process + + The core of the Linux operating system is known as the kernel, which is + loaded into memory when an embedded Linux system boots. The kernel + automatically probes, identifies, and initializes as much of your + system's hardware as possible, and then looks for an initial filesystem + that it can access in order to continue the boot process. + + The first filesystem mounted by Linux systems during the boot process + is known as a root filesystem, and is automatically mounted at the + Linux root directory /. Once mounted, the root filesystem provides the + Linux system with a basic directory structure that it can use to map + devices to Linux device nodes, access those devices, and locate, load, + and execute subsequent code such as system code or your custom + applications. + + All Linux systems start in essentially the same way. After loading the + kernel into memory and executing it, Linux systems execute a system + application known as init, which is typically found in /sbin/init on + Linux systems. The init process is process ID (PID) 1 on the system. It + reads the file /etc/inittab to identify the way in which the system + should boot and lists all other processes and programs that it should + start. + +Initial RAM Disks + + An initial RAM disk is a compressed filesystem image that is bundled + with a kernel. (For more information, refer to [10]Initial RAM Disks.) + If your system uses an initial RAM disk (initrd or initramfs), the boot + sequence includes one extra step. Instead of initially executing the + init process, the system uncompresses and mounts the initial RAM disk, + and then executes the file /linuxrc. This file can be a shell script + that lists other commands to execute, can be a multi-call binary such + as BusyBox, or can be a symbolic link to a multi-call binary or to + /sbin/init. + + Because init is a user program, located in a filesystem, the Linux + kernel must find and mount the first (or root) filesystem in order to + boot successfully. Ordinarily, available filesystems are listed in the + file /etc/fstab so the mount program can find them. But /etc/fstab is + itself a file, stored in a filesystem. Finding the very first + filesystem is a chicken-and-egg problem, and to solve it the kernel + developers created the kernel command-line option root=, which + specifies on which device the root filesystem exists. + +initrd + + When root= was first implemented, it would be either a floppy drive or + a partition on a hard drive. Today, the root filesystem can be on + dozens of different types of hardware, or spread across several + locations in a RAID. Its location can move around between reboots, as + with hot-pluggable USB devices on a system with multiple USB ports. The + root filesystem might be compressed, encrypted, or loopback-mounted. It + could even be located on a network server, requiring the kernel to + acquire a DHCP address, perform a DNS lookup, and log in to a remote + server (with username and password), all before the kernel can find and + run the first userspace program. + + Note: + + On desktop Linux systems that use the GRUB (Grand Unified Boot Loader) + boot loader, the system's initial RAM disk is usually stored as a + separate file external to the kernel. This file is typically located in + the /boot directory and is identified in the GRUB configuration file + (/etc/grub.conf). On most embedded systems, the initial RAM disk is + created as a file external to the kernel, but is bundled with the + kernel as a final step in the kernel build process. If you are using + GRUB, this device is identified via one of your boot arguments, the + root= parameter. + + As a result, root= does not provide enough information to the kernel. + Even including a great deal of special-case behavior in the kernel does + not help with device enumeration, encryption keys, or network logins + that vary from system to system. RAM disks such as initrd help to solve + this problem. + + For 2.4 and earlier kernels, initrd is still the only way to provide a + RAM-based root filesystem. Initrd is a RAM-based block device -- a + fixed-size chunk of memory that can be formatted and mounted like a + disk. Therefore, the contents of the RAM disk have to be formatted and + prepared with special tools, such as mke2fs and losetup. Additionally, + like all block devices, the RAM disk requires a filesystem driver to + interpret the data at run time, which imposes an artificial size limit + that either wastes space or limits capacity. + + RAM disks waste even more memory due to caching. Linux is designed to + cache all files and directory entries read from or written to block + devices, so Linux copies data to and from the RAM disk into the "page + cache" (for file data), and the "dentry cache" (for directory entries). + + Initrd was designed as front end to the root= device detection code, + not a replacement for it. When you boot a Linux system that uses an + initial RAM disk, the system uncompresses and mounts the initial RAM + disk, and then executes the file /linuxrc (which must therefore be + executable) before running init. The linuxrc file performs functions + such as logging onto the network, telling the kernel which block device + contains the root filesystem (using root= and pivot_root), and then + returns control to the kernel. Finally, the kernel mounts the root + filesystem and executes init. This process assumes that the root + filesystem was on a block device rather than a network share, and also + assumes that initrd isn't itself going to be the root filesystem. + + Because of these limitations with initrd, the 2.6 kernel developers + chose to implement a new mechanism for finding the initial filesystem - + initramfs. + +initramfs + + Initramfs is a mechanism in which the files in the Linux cache are + mounted like a filesystem, and retained until they're deleted or the + system reboots. Linux 2.6 kernels bundle a small RAM-based initial root + filesystem into the kernel, containing a program called init that the + kernel runs as its first program. Finding another filesystem containing + the root filesystem is now the job of this new init program. + + These RAM-based filesystems automatically grow or shrink to fit the + size of the data they contain. Adding files to a ramfs (or extending + existing files) automatically allocates more memory, and deleting or + truncating files frees that memory. Because there is no block device, + there is no duplication between the block device and the cache - the + copy in the cache is the only copy of the data. In addition, a system + using initramfs as its root filesystem doesn't need a filesystem driver + built into the kernel, because there are no block devices to interpret + as filesystems; there are simply files located in memory. Best of all, + this isn't new code, but a new application for the existing Linux + caching code, which means it adds almost no size, is very simple, and + is based on extremely well-tested infrastructure. + + The contents of an initramfs do not have to be general-purpose. For + example, if a given system's root filesystem is located on an encrypted + network block device, and the network address, login, and decryption + key are all to be found on a given USB device that requires a password + to access, the system's initramfs can have a special-purpose program + that knows all about this process, and makes it happen. Even better, + systems that don't need a large root filesystem do not need to switch + to another root filesystem. + + With initramfs, the kernel can return to following orders after it + launches init. Because the init program is run with PID 1, the real + root filesystem is initramfs until further notice, and the exec() + system call can be used to pass that process ID to another program, if + needed. + + Copyright © 2023 [11]Timesys Corporation. All Rights Reserved. + [12]Privacy Policy | [13]Cookie Policy | [14]Eula | [15]Terms of + Service | [16]Terms of Sale + Yocto Project and all related marks and logos are registered trademarks + of The Linux Foundation. This website is not, in any way, endorsed by + the Yocto Project or The Linux Foundation. + [17][timesys-github.png] [18][timesys-twitter.png] + [19][timesys-youtube.png] [20][squares1.svg] + +References + + Visible links: + 1. https://linuxlink.timesys.com/ + 2. https://linuxlink.timesys.com/ + 3. https://linuxlink.timesys.com/docs/ + 4. https://linuxlink.timesys.com/cves/demo + 5. https://linuxlink.timesys.com/guest/ + 6. https://linuxlink.timesys.com/register/ + 7. https://linuxlink.timesys.com/login/ + 8. https://linuxlink.timesys.com/docs/startup_overview#main-content + 9. https://linuxlink.timesys.com/ + 10. https://linuxlink.timesys.com/docs/initrd + 11. http://www.timesys.com/ + 12. https://linuxlink.timesys.com/about/privacy + 13. https://linuxlink.timesys.com/about/cookies + 14. https://linuxlink.timesys.com/about/eula + 15. https://linuxlink.timesys.com/about/tos + 16. https://linuxlink.timesys.com/about/termsofsale + 17. https://github.com/TimesysGit + 18. http://twitter.com/Timesys + 19. http://www.youtube.com/timesys + 20. http://www.timesys.com/ + + Hidden links: + 22. https://linuxlink.timesys.com/docs/startup_overview @@ -26,7 +26,6 @@ insmod /lib/modules/crypto/crc32c_generic.ko insmod /lib/modules/fs/ext4/ext4.ko insmod /lib/modules/drivers/block/nbd.ko nbd-client -N ROOT 10.0.0.2 /dev/nbd0 -mkdir /mnt mount -t ext4 /dev/nbd0 /mnt echo "Loading additional modules.." diff --git a/patches/uflbbl-boot-options.patch b/patches/uflbbl-boot-options.patch index 44e3717..ccf4c98 100644 --- a/patches/uflbbl-boot-options.patch +++ b/patches/uflbbl-boot-options.patch @@ -1,12 +1,26 @@ -diff -rauN uflbbl/src/boot.asm uflbbl-kernel-params-patch/src/boot.asm ---- uflbbl/src/boot.asm 2023-05-05 18:48:22.000000000 +0200 -+++ uflbbl-kernel-params-patch/src/boot.asm 2023-05-07 19:51:21.735659678 +0200 +diff -rauN a/src/boot.asm b/src/boot.asm +--- a/src/boot.asm 2023-05-05 18:48:22.000000000 +0200 ++++ b/src/boot.asm 2023-05-19 15:44:17.984926907 +0200 +@@ -468,10 +468,10 @@ + mov [READ_STATE], byte STATE_READ_INITRD + ; qemu initrd start location 7fab000, 133869568 (this is 128MB) too high for us, + ; kernel gives us alignment hints and hints where to load initrd to? +-; let's use 8MB, TODO: does the kernel release the initial ramdisk? I think so. is ++; let's use 6MB, TODO: does the kernel release the initial ramdisk? I think so. is + ; it relocating it's structures? or do we get fragmented heap and stuff? +- a32 mov [READ_DESTINATION_PTR], dword 0x00800000 +- a32 mov [INITRD_ADDRESS], dword 0x00800000 ++ a32 mov [READ_DESTINATION_PTR], dword 0x00580000 ++ a32 mov [INITRD_ADDRESS], dword 0x00580000 + a32 mov eax, [READ_DATA_SIZE] + a32 mov [INITRD_SIZE], eax + mov al, '!' @@ -1385,7 +1385,7 @@ dw 0 KERNEL_CMD_LINE: - db "debug loglevel=7 earlycon=uart8250,io,0x3f8,9600n8 console=tty0 console=ttyS0,9600n8 rdinit=/bin/sinit root=/dev/ram0 rootfstype=ramfs iommu=off", 0 -+ db "debug loglevel=7 earlycon=uart8250,io,0x3f8,9600n8 console=tty0 console=ttyS0,9600n8 init=/init iommu=off nomodeset nokaslr", 0 ++ db "debug loglevel=7 earlyprintk=vga earlycon=uart8250,io,0x3f8,9600n8 console=tty0 console=ttyS0,9600n8 init=/init iommu=off nomodeset", 0 KERNEL_CMD_SIZE equ $-KERNEL_CMD_LINE diff --git a/scripts/build.sh b/scripts/build.sh index 70ebf99..c851663 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -35,7 +35,7 @@ cd "${BASE}/src/stage0" # stage 0 host, build a 64-bit cross-compiler for i386, the host might # not have a packaged tcc at all or one not built for cross-compilation # TODO: we get a little bit too many cross compilers, but currently -# we cannot easily just the ones we want. +# we cannot easily build just the ones we want. if [ ! -x "${BASE}/build/stage0/bin/i386-tcc" ]; then rm -rf "tinycc-${TINYCC_VERSION}" @@ -70,7 +70,7 @@ else fi # build tcc with tcc from stage1 against musl from stage0, it should -# have no dependencies from the host anymore +# have no dependencies on the host anymore cd "${BASE}/src/stage1" @@ -302,6 +302,11 @@ if [ ! -f "${BASE}/build/stage1/lib/libz.a" ]; then --static make -j$CPUS make -j$CPUS install PREFIX="${BASE}/build/stage1" + # TOOD: do we need command line tools for ZIP? + #~ cd contrib/minizip + #~ make CC=/data/work/i486/build/stage1/bin/i386-tcc CFLAGS=-static + #~ cp minizip /data/work/i486/build/stage1/bin/zip + #~ cp miniunz /data/work/i486/build/stage1/bin/unzip cd .. else echo "stage1 zlib exists" @@ -321,7 +326,8 @@ if [ ! -x "${BASE}/build/stage1/bin/man" ]; then LDFLAGS="-static -L${BASE}/build/stage1/lib" BINM_PAGER=more EOF - ./configure + # TODO: can we patch out zlib support? Or patch in xz support? + ./configure make -j$CPUS make -j$CPUS install DESTDIR="${BASE}/build/stage1" cd .. @@ -371,6 +377,20 @@ else echo "stage1 samurai exists" fi +if [ ! -f "${BASE}/build/stage1/bin/joe" ]; then + rm -rf "joe-${JOE_VERSION}" + tar xf "${BASE}/downloads/joe-${JOE_VERSION}.tar.gz" + cd "joe-${JOE_VERSION}" + CC="${BASE}/build/stage1/bin/i386-tcc" \ + ./configure --prefix="${BASE}/build/stage1" \ + --enable-static --disable-shared + make -j$CPUS LDFLAGS=-static + make -j$CPUS install + cd .. +else + echo "stage1 joe exists" +fi + # TODO FROM HERE # TODO: have some way to deal with dependencies and with the user @@ -381,12 +401,6 @@ fi # and crunched, final binaries on the hard disk maybe dynamic # and "normal"..? -#~ cd ../joe -#~ CC=/data/work/i486/build/stage1/bin/i386-tcc \ - #~ ./configure --prefix=/data/work/i486/build/stage1 -#~ make LDFLAGS=-static -#~ make install - #~ cd ../less #~ CC=/data/work/i486/build/stage1/bin/i386-tcc ./configure --prefix=/data/work/i486/build/stage1 #~ make LDFLAGS=-static @@ -400,14 +414,6 @@ fi #~ cd ../lynx #~ CC=/data/work/i486/build/stage1/bin/i386-tcc CFLAGS='-march=i486 -mcpu=i486' ./configure --prefix=/data/work/i486/build/stage1 -#~ cd ../zlib -#~ CC=/data/work/i486/build/stage1/bin/i386-tcc ./configure --prefix=/data/work/i486/build/stage1 --static -#~ make -#~ cd contrib/minizip -#~ make CC=/data/work/i486/build/stage1/bin/i386-tcc CFLAGS=-static -#~ cp minizip /data/work/i486/build/stage1/bin/zip -#~ cp miniunz /data/work/i486/build/stage1/bin/unzip - #~ cd ../perp #~ cd lasagna #~ make CC=/data/work/i486/build/stage1/bin/i386-tcc diff --git a/scripts/create_ramdisk.sh b/scripts/create_ramdisk.sh index 816a77a..f30a46c 100755 --- a/scripts/create_ramdisk.sh +++ b/scripts/create_ramdisk.sh @@ -36,9 +36,10 @@ test -d "${RAMDISK}"/dev || mkdir "${RAMDISK}"/dev test -d "${RAMDISK}"/dev/pts || mkdir "${RAMDISK}"/dev/pts test -d "${RAMDISK}"/proc || mkdir "${RAMDISK}"/proc test -d "${RAMDISK}"/sys || mkdir "${RAMDISK}"/sys -#~ test -d "${RAMDISK}"/tmp || mkdir "${RAMDISK}"/tmp -#~ test -d "${RAMDISK}"/var || mkdir "${RAMDISK}"/var -#~ test -d "${RAMDISK}"/var/run || mkdir "${RAMDISK}"/var/run +test -d "${RAMDISK}"/tmp || mkdir "${RAMDISK}"/tmp +test -d "${RAMDISK}"/var || mkdir "${RAMDISK}"/var +test -d "${RAMDISK}"/var/run || mkdir "${RAMDISK}"/var/run +test -d "${RAMDISK}"/mnt || mkdir "${RAMDISK}"/mnt # just copy the stuff needed by '/init' test -d "${RAMDISK}/bin" || mkdir "${RAMDISK}/bin" diff --git a/scripts/download.sh b/scripts/download.sh index a5d9a42..6431b07 100755 --- a/scripts/download.sh +++ b/scripts/download.sh @@ -137,6 +137,14 @@ if [ ! -f "${BASE}/downloads/samurai-${SAMURAI_VERSION}.tar.gz" ]; then wget -O "${BASE}/downloads/samurai-${SAMURAI_VERSION}.tar.gz" "https://github.com/michaelforney/samurai/releases/download/${SAMURAI_VERSION}/samurai-${SAMURAI_VERSION}.tar.gz" fi +if [ ! -f "${BASE}/downloads/samurai-${SAMURAI_VERSION}.tar.gz" ]; then + wget -O "${BASE}/downloads/samurai-${SAMURAI_VERSION}.tar.gz" "https://github.com/michaelforney/samurai/releases/download/${SAMURAI_VERSION}/samurai-${SAMURAI_VERSION}.tar.gz" +fi + +if [ ! -f "${BASE}/downloads/joe-${JOE_VERSION}.tar.gz" ]; then + wget -O "${BASE}/downloads/joe-${JOE_VERSION}.tar.gz" "https://netcologne.dl.sourceforge.net/project/joe-editor/JOE%20sources/joe-${JOE_VERSION}/joe-${JOE_VERSION}.tar.gz" +fi + if [ ! -f "${BASE}/downloads/uflbbl-${UFLBBL_VERSION}.tar.gz" ]; then cd "${BASE}/downloads/" git clone git://git.andreasbaumann.cc/uflbbl.git "uflbbl-${UFLBBL_VERSION}" diff --git a/scripts/run_qemu.sh b/scripts/run_qemu.sh index e886ecc..9ce52de 100755 --- a/scripts/run_qemu.sh +++ b/scripts/run_qemu.sh @@ -2,7 +2,7 @@ qemu-nbd -f raw root.img -x ROOT & sleep 2 && \ -qemu-system-i386 -cpu 486 -m 24M \ +qemu-system-i386 -cpu 486 -m 18M -machine isapc \ -drive "file=floppy00,if=floppy,format=raw" \ -netdev user,id=net0,net=10.0.0.0/24,host=10.0.0.2,dhcpstart=10.0.0.16,hostfwd=tcp::8080-:80,hostfwd=udp::8081-:81 \ -device ne2k_isa,iobase=0x300,irq=10,netdev=net0 diff --git a/scripts/run_qemu_direct.sh b/scripts/run_qemu_direct.sh index e3d1704..f8de126 100755 --- a/scripts/run_qemu_direct.sh +++ b/scripts/run_qemu_direct.sh @@ -2,7 +2,7 @@ qemu-nbd -f raw root.img -x ROOT & sleep 2 && \ -qemu-system-i386 -cpu 486 -m 24M \ +qemu-system-i386 -cpu 486 -m 24M -machine isapc \ -kernel bzImage -initrd ramdisk.img \ -append "debug loglevel=7 earlycon=vga earlycon=uart8250,io,0x3f8,9600n8 console=tty0 console=ttyS0,9600n8 iommu=off nomodeset init=/init" \ -netdev user,id=net0,net=10.0.0.0/24,host=10.0.0.2,dhcpstart=10.0.0.16,hostfwd=tcp::8080-:80 \ |