big-img, chainload self
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@
|
|||||||
*.iso
|
*.iso
|
||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
*.tmp
|
||||||
|
|||||||
20
Makefile
20
Makefile
@@ -8,6 +8,7 @@ MYAS ?= gcc
|
|||||||
OBJ_EXT ?= .o
|
OBJ_EXT ?= .o
|
||||||
OUT_EXT ?= .img
|
OUT_EXT ?= .img
|
||||||
RUN ?= bios_hello_world
|
RUN ?= bios_hello_world
|
||||||
|
TMP_EXT ?= .tmp
|
||||||
|
|
||||||
INS := $(wildcard *$(IN_EXT))
|
INS := $(wildcard *$(IN_EXT))
|
||||||
OUTS := $(patsubst %$(IN_EXT),%$(OUT_EXT),$(INS))
|
OUTS := $(patsubst %$(IN_EXT),%$(OUT_EXT),$(INS))
|
||||||
@@ -24,7 +25,24 @@ all: $(OUTS)
|
|||||||
$(MYAS) -c -o '$@' '$<'
|
$(MYAS) -c -o '$@' '$<'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *$(OBJ_EXT) *$(OUT_EXT)
|
rm -fr *$(OBJ_EXT) *$(OUT_EXT) *$(TMP_EXT)
|
||||||
|
|
||||||
run: all
|
run: all
|
||||||
qemu-system-i386 '$(RUN)$(OUT_EXT)'
|
qemu-system-i386 '$(RUN)$(OUT_EXT)'
|
||||||
|
|
||||||
|
BIG_IMG_DIR := big_img$(TMP_EXT)
|
||||||
|
BOOT_DIR := $(BIG_IMG_DIR)/boot
|
||||||
|
GRUB_DIR := $(BOOT_DIR)/grub
|
||||||
|
big-img: all
|
||||||
|
rm -rf '$(BIG_IMG_DIR)'
|
||||||
|
mkdir -p '$(GRUB_DIR)'
|
||||||
|
for out in $(OUTS); do\
|
||||||
|
printf "menuentry \"$${out%.*}\" {\n chainloader /boot/$$out\n}\n" >> '$(GRUB_DIR)/grub.cfg';\
|
||||||
|
cp "$$out" '$(BOOT_DIR)';\
|
||||||
|
done
|
||||||
|
# TODO why does this fail to boot properly?
|
||||||
|
#make -C multiboot/hello-world
|
||||||
|
#mkdir -p '$(BOOT_DIR)/multiboot'
|
||||||
|
#printf "menuentry \"multiboot/hello-world\" {\n chainloader /boot/multiboot/hello-world.img\n}\n" >> '$(GRUB_DIR)/grub.cfg';\
|
||||||
|
#cp multiboot/hello-world/main.img '$(BOOT_DIR)/multiboot/hello-world.img'
|
||||||
|
grub-mkrescue -o 'big.img' '$(BIG_IMG_DIR)'
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -10,6 +10,9 @@ Hello world programs that run without an operating system.
|
|||||||
1. BIOS
|
1. BIOS
|
||||||
1. [BIOS one char](bios_one_char.S)
|
1. [BIOS one char](bios_one_char.S)
|
||||||
1. [BIOS hello world](bios_hello_world.S)
|
1. [BIOS hello world](bios_hello_world.S)
|
||||||
|
1. [BIOS newline](bios_newline.S)
|
||||||
|
1. [BIOS carriage return](bios_carriage_return.S)
|
||||||
|
1. [BIOS clear screen](bios_clear_screen.S)
|
||||||
1. APM
|
1. APM
|
||||||
1. [APM shutdown](apm_shutdown.S)
|
1. [APM shutdown](apm_shutdown.S)
|
||||||
1. [APM shutdown 2](apm_shutdown2.S)
|
1. [APM shutdown 2](apm_shutdown2.S)
|
||||||
@@ -31,6 +34,8 @@ Hello world programs that run without an operating system.
|
|||||||
|
|
||||||
sudo apt-get install build-essential gnu-efi qemu nasm xorriso
|
sudo apt-get install build-essential gnu-efi qemu nasm xorriso
|
||||||
|
|
||||||
|
### Emulator
|
||||||
|
|
||||||
Run the default program on QEMU:
|
Run the default program on QEMU:
|
||||||
|
|
||||||
make run
|
make run
|
||||||
@@ -42,7 +47,9 @@ Run a given program:
|
|||||||
|
|
||||||
Tested on Ubuntu 14.04 AMD64.
|
Tested on Ubuntu 14.04 AMD64.
|
||||||
|
|
||||||
To run on real hardware, insert an USB, determine its device (`/dev/sdX`) with:
|
### Real hardware
|
||||||
|
|
||||||
|
Insert an USB, determine its device (`/dev/sdX`) with:
|
||||||
|
|
||||||
sudo lsblk
|
sudo lsblk
|
||||||
sudo fdisk -l
|
sudo fdisk -l
|
||||||
@@ -58,3 +65,15 @@ Then:
|
|||||||
- choose to boot from the USB
|
- choose to boot from the USB
|
||||||
|
|
||||||
Tested on: ThinkPad T400.
|
Tested on: ThinkPad T400.
|
||||||
|
|
||||||
|
#### Big image
|
||||||
|
|
||||||
|
Create a `big.img` that contains all examples that can be booted from GRUB:
|
||||||
|
|
||||||
|
make big-img
|
||||||
|
|
||||||
|
Now if you do:
|
||||||
|
|
||||||
|
sudo dd if=big.img of=/dev/sdX
|
||||||
|
|
||||||
|
you can test several examples with a single USB burn, which is much faster.
|
||||||
|
|||||||
26
bios_carriage_return.S
Normal file
26
bios_carriage_return.S
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
What happens when a newline is output with bios.
|
||||||
|
|
||||||
|
Outcome:
|
||||||
|
|
||||||
|
hello
|
||||||
|
world
|
||||||
|
|
||||||
|
Carriage returns are needed just like in old days.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
BEGIN
|
||||||
|
mov $msg, %si
|
||||||
|
mov $0x0e, %ah
|
||||||
|
loop:
|
||||||
|
lodsb
|
||||||
|
or %al, %al
|
||||||
|
jz halt
|
||||||
|
int $0x10
|
||||||
|
jmp loop
|
||||||
|
halt:
|
||||||
|
hlt
|
||||||
|
msg:
|
||||||
|
.asciz "hello\n\rworld"
|
||||||
|
END
|
||||||
29
bios_clear_screen.S
Normal file
29
bios_clear_screen.S
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Clear screen by scrolling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
Print one char to ensure that something will be claered.
|
||||||
|
|
||||||
|
On some systems, BIOS messages get automatically cleared. Not the case for QEMU 2.0.0.
|
||||||
|
*/
|
||||||
|
mov $0x0E40, %ax
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
/* Function ID. */
|
||||||
|
mov $0x06, %ah
|
||||||
|
/* nr. of lines to scroll, 00 means clear window. */
|
||||||
|
mov $0x0, %al
|
||||||
|
/* TODO: I think this is the style. */
|
||||||
|
mov $0x7, %bh
|
||||||
|
/* CH,CL: row,column upper left corner (00:00) */
|
||||||
|
mov $0x0, %cx
|
||||||
|
/* DH,DL: row,column lower right corner (24:79) */
|
||||||
|
mov $0x184f, %dx
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
hlt
|
||||||
|
END
|
||||||
26
bios_newline.S
Normal file
26
bios_newline.S
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
What happens when a newline is output with bios.
|
||||||
|
|
||||||
|
Outcome:
|
||||||
|
|
||||||
|
hello
|
||||||
|
world
|
||||||
|
|
||||||
|
Carriage returns are needed just like in old days.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
BEGIN
|
||||||
|
mov $msg, %si
|
||||||
|
mov $0x0e, %ah
|
||||||
|
loop:
|
||||||
|
lodsb
|
||||||
|
or %al, %al
|
||||||
|
jz halt
|
||||||
|
int $0x10
|
||||||
|
jmp loop
|
||||||
|
halt:
|
||||||
|
hlt
|
||||||
|
msg:
|
||||||
|
.asciz "hello\nworld"
|
||||||
|
END
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
Print a single `@` character with the BIOS.
|
Print a single `@` character with the BIOS.
|
||||||
|
|
||||||
More minimal than the hello world.
|
More minimal than the hello world.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
BEGIN
|
BEGIN
|
||||||
mov $0x40, %al
|
/*
|
||||||
mov $0x0e, %ah
|
40 == ASCII for '@'
|
||||||
|
0E == BIOS function ID.
|
||||||
|
*/
|
||||||
|
mov $0x0E40, %ax
|
||||||
int $0x10
|
int $0x10
|
||||||
hlt
|
hlt
|
||||||
END
|
END
|
||||||
|
|||||||
13
grub/Makefile
Normal file
13
grub/Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.POSIX:
|
||||||
|
|
||||||
|
.PHONY: clean run
|
||||||
|
|
||||||
|
main.img:
|
||||||
|
make -C '../mbrs' && cp '../bios_hello_world.img.sym' 'iso/boot/main.img'
|
||||||
|
grub-mkrescue -o '$@' iso
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f iso/boot/*.img *.img
|
||||||
|
|
||||||
|
run: main.img
|
||||||
|
qemu-system-i386 -hda '$<'
|
||||||
@@ -11,3 +11,5 @@ This example uses a file, but the most common way to use it is with:
|
|||||||
chainloader +1
|
chainloader +1
|
||||||
|
|
||||||
which uses the first sector of some partition instead of a file.
|
which uses the first sector of some partition instead of a file.
|
||||||
|
|
||||||
|
TODO: why does it fail for hybrid ISO images? <http://superuser.com/questions/154134/grub-how-to-boot-into-iso-partition#comment1337357_154271>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
set timeout=0
|
menuentry "hello-world" {
|
||||||
set default="0"
|
|
||||||
menuentry "main" {
|
|
||||||
chainloader /boot/main.img
|
chainloader /boot/main.img
|
||||||
}
|
}
|
||||||
|
# Reload ourselves again.
|
||||||
|
menuentry "self +1" {
|
||||||
|
chainloader +1
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user