Bochs works, failed PIT and beep attempts

This commit is contained in:
Ciro Santilli
2015-09-30 19:03:23 +02:00
parent 173111e0d0
commit cba0757990
12 changed files with 214 additions and 15 deletions

View File

@@ -30,6 +30,13 @@ clean:
run: all
qemu-system-i386 '$(RUN)$(OUT_EXT)'
bochs: all
bochs -qf /dev/null \
'ata0-master: type=disk, path="$(RUN)$(OUT_EXT)", mode=flat, cylinders=1, heads=1, spt=1' \
'boot: disk' \
'display_library: sdl' \
'megs: 128'
BIG_IMG_DIR := big_img$(TMP_EXT)
BOOT_DIR := $(BIG_IMG_DIR)/boot
GRUB_DIR := $(BOOT_DIR)/grub

View File

@@ -29,8 +29,11 @@ Hello world programs that run without an operating system.
1. [Interrupt zero divide](interrupt_zero_divide.S)
1. in
1. [in keyboard](in_keyboard.S)
1. [in PIT (TODO)](in_pit.S)
1. [in RTC](in_rtc.S)
1. [in PIT (TODO)](in_pit.S)
1. [in beep (TODO)](in_beep.S)
1. [in beep_kernel (TODO)](in_beep_kernel.S)
1. [in beep_illinois (TODO)](in_beep_illinois.S)
1. [in mouse (TODO)](in_mouse.S)
1. APM
1. [APM shutdown](apm_shutdown.S)
@@ -52,7 +55,7 @@ Hello world programs that run without an operating system.
## Getting started
sudo apt-get install build-essential gnu-efi qemu nasm xorriso
sudo apt-get install bochs bochs-sdl build-essential gnu-efi qemu nasm xorriso
### Emulator
@@ -65,6 +68,10 @@ Run a given program:
make run RUN=min
make run RUN=bios_one_char
Use Bochs instead of QEMU:
make bochs RUN=min
Tested on Ubuntu 14.04 AMD64.
### Real hardware

17
TODO.md
View File

@@ -8,7 +8,20 @@
- instructions
- cache: wbinvd
- outb inb
- inb outb
Answer with bare metal Tetris
- http://stackoverflow.com/questions/8365746/what-does-outb-in-att-asm-mean
- http://stackoverflow.com/questions/3215878/what-are-in-out-instructions-in-x86-used-for
- http://wiki.osdev.org/Text_UI
Port 0x80 on Linux kenrnel: https://github.com/torvalds/linux/blob/v4.2/arch/x86/boot/boot.h#L78 http://stackoverflow.com/questions/6793899/what-does-the-0x80-port-address-connects
Port 0x61 speaker https://courses.engr.illinois.edu/ece390/books/labmanual/io-devices-speaker.html
- http://wiki.osdev.org/GUI
- lgdtl, paging http://stackoverflow.com/questions/21128311/the-physical-address-of-global-descriptor-table http://stackoverflow.com/questions/7415515/problem-accessing-control-registers-cr0-cr2-cr3
- lidtl, interrupts, IDTR
- https://en.wikipedia.org/wiki/Double_fault
@@ -62,7 +75,7 @@
- play with hardware
- keyboard through interrupt (high level int 16 bios done)
- keyboard through interrupt (high level BIOS int 16 that waits for input done)
- keyboard protected mode: http://stackoverflow.com/questions/219120/x86-assembly-protected-mode-keyboard-access
- set a pixel on screen in protected mode http://stackoverflow.com/questions/14419088/assembly-draw-a-pixel-on-the-screen-in-protected-mode
- USB

View File

@@ -22,6 +22,8 @@
- <https://github.com/scanlime/metalkit> A more automated / general bare metal compilation system. Untested, but looks promising.
- <https://courses.engr.illinois.edu/ece390/books/labmanual/index.html> Illinois course from 2004
The following did not work on my machine out of the box:
- <https://github.com/apparentlymart/ToyOS>

View File

@@ -44,6 +44,8 @@ Print a single immediate byte or 8 bit register.
Usage: character 'A' (ASCII 61):
PUTS(61)
Clobbers: ax
*/
#define PUTC(c) \
mov $0x0E, %ah;\
@@ -54,21 +56,23 @@ Usage: character 'A' (ASCII 61):
Convert a byte to hex ASCII value.
c: r/m8 byte to be converted
Output: two ASCII characters, is stored in `al:bl`
Clobbers: ax
http://stackoverflow.com/questions/3853730/printing-hexadecimal-digits-with-assembly
*/
#define HEX(c) GAS_HEX c
.macro GAS_HEX c
mov \c, %al
mov \c, %bl
mov \c, %ah
shr $4, %al
GAS_HEX_NIBBLE al
and $0x0F, %bl
GAS_HEX_NIBBLE bl
and $0x0F, %ah
GAS_HEX_NIBBLE ah
.endm
/*
Convert the low nibble of a r8 reg to ASCII of 8-bit in-place.
reg: r8 to be converted
Clobbered registers: none
Output: stored in reg itself. Letters are uppercase.
*/
.macro GAS_HEX_NIBBLE reg
@@ -84,10 +88,16 @@ letter:
end:
.endm
/*
Print a byte as two hexadecimal digits.
Clobbers: ax, dl
*/
#define PRINT_HEX(reg) \
HEX(<reg>);\
mov %ah, %dl;\
PUTC(%al);\
PUTC(%bl)
PUTC(%dl)
#define PRINT_NEWLINE \
PUTC($0x0A);\

10
in.md
View File

@@ -1,8 +1,16 @@
# in
# out
IO operations.
Do not work with immediates: only registers or memory locations.
## Bit 0x80
TODO http://wiki.osdev.org/CMOS#Getting_Current_Date_and_Time_from_RTC says:
/* since the 0x80 bit of al is not set, NMI is active */
out 0x70,al
out 0x70, al
What does it mean?

27
in_beep.S Normal file
View File

@@ -0,0 +1,27 @@
/*
The beep circuit is linked to the PIT.
I think it is possible to make a beep after a certain amount of time passes.
http://fly.srk.fer.hr/GDM/articles/sndmus/speaker1.html
*/
#include "common.h"
.equ div, 1193181 / 1000;
BEGIN
start:
PUTC($0x61)
mov $0xb6, %al
out %al, $0x43 /* Ctr 2, squarewave, load, binary */
mov div, %al
out %al, $0x42 /* LSB of counter */
mov div, %al
shr $8, %al
out %al, $0x42 /* MSB of counter */
in $0x61, %al /* Dummy read of System Control Port B */
mov $0x03, %al
out %al, $0x61 /* Enable timer 2 output to speaker */
jmp start
END

37
in_beep_illinois.S Normal file
View File

@@ -0,0 +1,37 @@
/*
https://courses.engr.illinois.edu/ece390/books/labmanual/io-devices-speaker.html
TODO not working on QEMU
*/
#include "common.h"
BEGIN
start:
PUTC($0x61)
movb $182,%al # Prepare the speaker for the
outb %al, $0x43 # note.
movw $4560,%ax # Frequency number (in decimal)
# for middle C.
outb %al, $0x42 # Output low byte.
movb %ah,%al # Output high byte.
outb %al, $0x42
inb $0x61,%al # Turn on note (get value from
# port 61h).
orb $0b00000011,%al # Set bits 1 and 0.
outb %al, $0x61 # Send new value.
movw $25,%bx # Pause for duration of note.
.pause1:
movw $65535,%cx
.pause2:
decw %cx
jne .pause2
decw %bx
jne .pause1
inb $0x61,%al # Turn off note (get value from
# port 61h).
andb $0b11111100,%al # Reset bits 1 and 0.
outb %al, $0x61 # Send new value.
jmp start
END

25
in_beep_kernel.S Normal file
View File

@@ -0,0 +1,25 @@
/*
Extracted from: https://github.com/torvalds/linux/blob/v4.2/arch/x86/realmode/rm/wakemain.c#L38
TODO not working on QEMU
*/
#include "common.h"
.equ div, 1193181 / 1000;
BEGIN
start:
PUTC($0x61)
mov $0xb6, %al
out %al, $0x43 /* Ctr 2, squarewave, load, binary */
mov div, %al
out %al, $0x42 /* LSB of counter */
mov div, %al
shr $8, %al
out %al, $0x42 /* MSB of counter */
in $0x61, %al /* Dummy read of System Control Port B */
mov $0x03, %al
out %al, $0x61 /* Enable timer 2 output to speaker */
jmp start
END

View File

@@ -1,10 +1,46 @@
/*
TODO http://wiki.osdev.org/PIT
# PIT
TODO get working
TODO answer with example http://stackoverflow.com/questions/13950264/does-using-tsc-as-clock-source-improve-timer-and-scheduling-granularity
Programmable interrupt timer.
Can generate periodic interrupts, or sounds.
The kernel has a Morse code encoder with it. https://github.com/torvalds/linux/blob/v4.2/arch/x86/realmode/rm/wakemain.c#L38
Going to use in 0x40
## 1193181
Magic number that is the frequency of the oscillator.
http://f.osdev.org/viewtopic.php?f=1&t=15503
## Bibliography
- https://en.wikipedia.org/wiki/Intel_8253
- http://wiki.osdev.org/PIT
- http://kernelx.weebly.com/programmable-interval-timer.html
*/
#include "common.h"
#define PIT_CHANNEL0 $0x40
#define PIT_CHANNEL1 $0x41
#define PIT_CHANNEL2 $0x42
#define PIT_CMDREG $0x43
BEGIN
hlt
start:
#u16 div = 1193181/hz;
# Linux kernel
#outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */
#outb(div, 0x42); /* LSB of counter */
#outb(div >> 8, 0x42); /* MSB of counter */
#enable = 0x03; /* Turn on speaker */
#inb(0x61); /* Dummy read of System Control Port B */
#outb(enable, 0x61); /* Enable timer 2 output to speaker */
END

View File

@@ -1,14 +1,35 @@
/*
TODO http://wiki.osdev.org/RTC
# in RTC
Real time clock.
Gives wall time with precision of seconds.
Uses a separate battery to keep going.
http://stackoverflow.com/questions/1465927/how-can-i-access-system-time-using-nasm
http://wiki.osdev.org/RTC
http://wiki.osdev.org/CMOS
Kenrel 4.2 usage: https://github.com/torvalds/linux/blob/v4.2/arch/x86/kernel/rtc.c#L121
http://stackoverflow.com/questions/1465927/how-can-i-access-system-time-using-nasm
## Milliseconds
Not possible. Must use the PIT.
## Time zone
QEMU uses UTC.
*/
#include "common.h"
BEGIN
/*
TODO what do those numbers mean? Where is this all documented?
*/
.equ RTCaddress, 0x70
.equ RTCdata, 0x71
@@ -68,6 +89,4 @@ update_in_progress:
PRINT_NEWLINE
jmp update_in_progress
hlt
END

8
nasm/bios_one_char.asm Normal file
View File

@@ -0,0 +1,8 @@
org 0x7c00
bits 16
cli
mov ax, 0x0E61
int 0x10
hlt
times 510 - ($-$$) db 0
dw 0xaa55