├── ut ├── readme ├── makefile └── ut.c ├── c-bootloader ├── r.sh ├── pc │ ├── readme │ ├── cb.c │ ├── makefile │ ├── l.ld │ └── bhp.S ├── code16gcc.h ├── mk.sh ├── c.sh ├── cb.sh ├── cpp │ ├── io.h │ ├── global_object │ │ ├── io.h │ │ ├── io.cpp │ │ ├── makefile │ │ ├── cpp.ld │ │ └── cppb.cpp │ ├── io.cpp │ ├── makefile │ ├── cppb.cpp │ └── cpp.ld ├── readme ├── bh.asm ├── bh.s ├── linker.ld ├── linker_dos.ld ├── as.ld ├── l.ld ├── mkimg.sh ├── cb.c ├── vbr.c ├── cppb.cpp ├── bhp.S ├── makefile └── fat.c ├── script ├── q.sh ├── bss_test.sh └── cp2img.sh ├── include ├── common.h ├── systask.h ├── type.h ├── font_rawdata.h ├── mm.h ├── k_ctype.h ├── syscall.h ├── k_assert.h ├── draw_func.h ├── tty.h ├── storage.h ├── irq.h ├── kl_global.h ├── vfs.h ├── k_stdlib.h ├── endian.h ├── io.h ├── vga.h ├── romfs.h ├── k_string.h ├── k_stdio.h ├── console.h ├── protect.h ├── pm.h ├── keyboard.h ├── elf.h └── process.h ├── clock.h ├── others ├── mount.romfs └── makefile ├── io_port.h ├── process_const.h ├── io ├── makefile ├── k_stdio_k.c └── k_stdio.c ├── rule.mk ├── mm ├── makefile └── mm.c ├── fs ├── vfs.c ├── makefile └── romfs.c ├── asm_syscall.h ├── apps ├── start.S ├── echo.c └── makefile ├── g1.sh ├── k_assert.c ├── vga ├── makefile ├── as.ld ├── draw_func.c └── set_mode.S ├── bss.lds ├── clock.c ├── bss_dos.lds ├── kernel_loader ├── klp.ld ├── makefile ├── protected_code.c └── kloader_init.S ├── tty ├── makefile ├── tty.c ├── console.c └── keyboard.c ├── k.ld ├── asm_func.S ├── k_stdlib.c ├── storage.c ├── asm_syscall.S ├── b.c ├── systask.c ├── c_init.s ├── README.md ├── b_by_bootloader.c ├── c_init_by_boot_loader.s ├── syscall.c └── makefile /ut/readme: -------------------------------------------------------------------------------- 1 | do unit test 2 | -------------------------------------------------------------------------------- /c-bootloader/r.sh: -------------------------------------------------------------------------------- 1 | qemu -fda floppy.img -boot a 2 | -------------------------------------------------------------------------------- /c-bootloader/pc/readme: -------------------------------------------------------------------------------- 1 | enter protected mode and use C code. 2 | -------------------------------------------------------------------------------- /script/q.sh: -------------------------------------------------------------------------------- 1 | qemu-system-i386 -fda boot.img -S -gdb tcp::1234 2 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | .set loader_base_phy_addr, (0x9000*0x10) 2 | 3 | 4 | -------------------------------------------------------------------------------- /clock.h: -------------------------------------------------------------------------------- 1 | #ifndef CLOCK_H 2 | #define CLOCK_H 3 | 4 | void clock_handler(int irq); 5 | #endif 6 | -------------------------------------------------------------------------------- /c-bootloader/code16gcc.h: -------------------------------------------------------------------------------- 1 | #ifndef _CODE16GCC_H_ 2 | #define _CODE16GCC_H_ 3 | __asm__(".code16gcc\n"); 4 | #endif 5 | -------------------------------------------------------------------------------- /others/mount.romfs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # example for mounting romfs. 3 | #sudo mount -t romfs -o loop rom.fs /mnt/ 4 | 5 | -------------------------------------------------------------------------------- /include/systask.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSTASK_H 2 | #define SYSTASK_H 3 | void task_sys(void); 4 | void task_mm(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /io_port.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_PORT_H 2 | #define IO_PORT_H 3 | #define INT_M_CTLMASK 0x21 4 | #define INT_S_CTLMASK 0xa1 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /c-bootloader/mk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dd if=/dev/zero of=floppy.img bs=1024 count=1440 3 | dd if=vbr.bin of=floppy.img bs=1 count=512 conv=notrunc 4 | 5 | -------------------------------------------------------------------------------- /process_const.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESS_CONST_H 2 | #define PROCESS_CONST_H 3 | 4 | // prefix P_ means process structure 5 | #define P_EAX_OFFSET 44 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /script/bss_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # test bss program 3 | # make c_init.bin 4 | dd if=c_init.bin of=boot.img bs=512 count=1 5 | dd if=/dev/zero of=boot.img skip=1 seek=1 bs=512 count=2879 6 | -------------------------------------------------------------------------------- /c-bootloader/c.sh: -------------------------------------------------------------------------------- 1 | gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o vbr.o vbr.c 2 | ld -static -Tlinker.ld -nostdlib --nmagic -o vbr.elf vbr.o 3 | objcopy -O binary vbr.elf vbr.bin 4 | -------------------------------------------------------------------------------- /c-bootloader/cb.sh: -------------------------------------------------------------------------------- 1 | gcc -c cb.c 2 | ld -static -Tl.ld -nostdlib -o cb.elf cb.o 3 | objcopy -R .pdr -R .comment -R.note -S -O binary cb.elf cb.bin 4 | dd if=cb.bin of=floppy.img bs=1 count=512 conv=notrunc 5 | -------------------------------------------------------------------------------- /others/makefile: -------------------------------------------------------------------------------- 1 | genromfs: genromfs.o 2 | gcc -o $@ $< 3 | genromfs.o: genromfs.c 4 | gcc -o $@ -c $< 5 | 6 | genromfs_2.o: genromfs_2.c 7 | gcc -o $@ -c $< 8 | clean: 9 | rm -rf *.o genromfs 10 | -------------------------------------------------------------------------------- /io/makefile: -------------------------------------------------------------------------------- 1 | ifdef COMSPEC 2 | # in windows 3 | include ..\rule.mk 4 | else 5 | include ../rule.mk 6 | endif 7 | 8 | sources = k_stdio.c k_stdio_k.c 9 | include $(sources:.c=.d) 10 | 11 | .PHONE: clean 12 | 13 | clean: 14 | rm -rf *.o 15 | -------------------------------------------------------------------------------- /c-bootloader/cpp/io.h: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | #ifndef IO_H 3 | #define IO_H 4 | 5 | class Io 6 | { 7 | public: 8 | Io(); 9 | ~Io(); 10 | void print(const char *s); 11 | private: 12 | const char *str_; 13 | }; 14 | 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /c-bootloader/cpp/global_object/io.h: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | #ifndef IO_H 3 | #define IO_H 4 | 5 | class Io 6 | { 7 | public: 8 | Io(); 9 | ~Io(); 10 | void print(const char *s); 11 | private: 12 | const char *str_; 13 | }; 14 | 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /rule.mk: -------------------------------------------------------------------------------- 1 | CFLAGS = -DIPC -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -Iinclude -I../include 2 | ASFLAGS = --32 3 | LDFLAGS = -m elf_i386 4 | CC=gcc 5 | 6 | %.d: %.c 7 | set -e; rm -f $@ ; gcc -MM $(CFLAGS) $< > $@.$$$$ ; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@ ; rm -f $@.$$$$ 8 | 9 | -------------------------------------------------------------------------------- /c-bootloader/pc/cb.c: -------------------------------------------------------------------------------- 1 | //__asm__(".code16gcc\n"); 2 | 3 | 4 | void main(void) 5 | { 6 | unsigned char *vb = (unsigned char *)0xb8000; 7 | *vb = 'A'; 8 | *(unsigned char *)0xb8001 = 0xc; 9 | *(unsigned char *)0xb8002 = 'B'; 10 | *(unsigned char *)0xb8003 = 0xc; 11 | while(1); 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /mm/makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -O0 2 | #ASFLAGS = --32 3 | #LDFLAGS = -m elf_i386 4 | 5 | ifdef COMSPEC 6 | # in windows 7 | include ..\rule.mk 8 | else 9 | include ../rule.mk 10 | endif 11 | 12 | sources = mm.c 13 | include $(sources:.c=.d) 14 | 15 | 16 | -------------------------------------------------------------------------------- /c-bootloader/cpp/io.cpp: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | Io::Io():str_("data member\r\n") 3 | { 4 | print("ctor\r\n"); 5 | print(str_); 6 | } 7 | Io::~Io() 8 | { 9 | print("dtor\r\n"); 10 | } 11 | 12 | void Io::print(const char *s) 13 | { 14 | while(*s) 15 | { 16 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 17 | s++; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fs/vfs.c: -------------------------------------------------------------------------------- 1 | #include "vfs.h" 2 | 3 | SuperBlock *fs_type[MAX_SUPER_BLOCK]; 4 | 5 | int register_file_system(SuperBlock *type, u32 id) 6 | { 7 | if (fs_type[id] == 0) 8 | { 9 | fs_type[id] = type; 10 | return 0; 11 | } 12 | return -1; 13 | 14 | } 15 | 16 | int unregister_file_system(SuperBlock *type, u32 id) 17 | { 18 | fs_type[id] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /c-bootloader/cpp/global_object/io.cpp: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | Io::Io():str_("data member\r\n") 3 | { 4 | print("ctor\r\n"); 5 | print(str_); 6 | } 7 | Io::~Io() 8 | { 9 | print("dtor\r\n"); 10 | } 11 | 12 | void Io::print(const char *s) 13 | { 14 | while(*s) 15 | { 16 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 17 | s++; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /include/type.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPE_H 2 | #define TYPE_H 3 | typedef signed char s8; 4 | typedef signed short s16; 5 | typedef signed int s32; 6 | 7 | typedef unsigned char u8; 8 | typedef unsigned short u16; 9 | typedef unsigned int u32; 10 | 11 | typedef unsigned long long u64; 12 | 13 | 14 | #define MAG_CH_PANIC '\002' 15 | #define MAG_CH_ASSERT '\003' 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /asm_syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_SYSCALL_H 2 | #define ASM_SYSCALL_H 3 | 4 | #define INT_VECTOR_SYS_CALL 0x90 5 | #define _NR_GET_TICKS 0 6 | #define _NR_SET_VGA_MODE 1 7 | #define _NR_WRITE 2 8 | #define _NR_SENDREC 3 9 | #define _NR_PRINTK 4 10 | #define _NR_APP_PRINT 5 11 | 12 | #define NR_SYS_CALL 6 13 | 14 | //int get_ticks(void); 15 | //int set_vga_mode(void); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /fs/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -I../include 2 | 3 | all: vfs.o romfs.o 4 | 5 | vfs.o: vfs.c ../include/vfs.h ../include/type.h ../include/storage.h 6 | gcc $(CFLAGS) -c $< 7 | 8 | romfs.o: romfs.c ../include/type.h ../include/endian.h ../include/type.h \ 9 | ../include/romfs.h 10 | gcc $(CFLAGS) -c $< 11 | 12 | clean: 13 | rm -rf *.o 14 | -------------------------------------------------------------------------------- /include/font_rawdata.h: -------------------------------------------------------------------------------- 1 | #ifndef FONT_RAWDATA_H 2 | #define FONT_RAWDATA_H 3 | #include "type.h" 4 | 5 | extern u8 str[]; 6 | extern int wb; 7 | extern int hb; 8 | extern u8 ch_data[]; 9 | extern int ch_wb; 10 | extern int ch_hb; 11 | 12 | extern int pe_320_180_256_wb; 13 | extern int pe_320_180_256_hb; 14 | extern u8 pe_320_180_256_bmp[]; 15 | extern u8 pe_320_180_256_palette_data[]; 16 | #endif 17 | -------------------------------------------------------------------------------- /include/mm.h: -------------------------------------------------------------------------------- 1 | #ifndef MM_H 2 | #define MM_H 3 | 4 | #include "type.h" 5 | #include "k_stdio.h" 6 | 7 | extern u32 memory_used; 8 | extern u32 memsize_mb; 9 | 10 | int mm_init(void); 11 | u32 memtest(volatile u32 start, volatile u32 end); 12 | void *alloc_mem(void); 13 | void free_mem(void *mem_addr); 14 | int do_fork(void); 15 | void do_wait(void); 16 | void do_exit(int status); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /apps/start.S: -------------------------------------------------------------------------------- 1 | .code32 2 | .text 3 | 4 | .extern main 5 | .extern exit 6 | 7 | .global cstart 8 | cstart: 9 | call main 10 | push %eax 11 | call exit 12 | 13 | .data 14 | .global __romfs_start__ 15 | .global __romfs_end__ 16 | .global __bss_start__ 17 | .global __bss_end__ 18 | 19 | __romfs_start__: .int 0x0 20 | __romfs_end__: .int 0x0 21 | __bss_start__: .int 0x0 22 | __bss_end__: .int 0x0 23 | 24 | -------------------------------------------------------------------------------- /ut/makefile: -------------------------------------------------------------------------------- 1 | include ../rule.mk 2 | 3 | ut: ut.o ../io/k_stdio_k.o ../io/k_stdio.o 4 | $(CC) -std=c99 -m32 -o $@ $^ 5 | ut.o: ut.c 6 | $(CC) -std=c99 -m32 -fno-builtin -g -Iinclude -I../include -c $< 7 | 8 | io/k_stdio.o: io 9 | (cd ../io; make k_stdio.o) 10 | io/k_stdio_k.o: io 11 | (cd ../io; make k_stdio_k.o) 12 | 13 | .PHONE: clean distclean kloaderp.bin 14 | 15 | clean: 16 | rm -rf *.o ut 17 | -------------------------------------------------------------------------------- /c-bootloader/readme: -------------------------------------------------------------------------------- 1 | ref: http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html 2 | write bootloader by c (practice) 3 | 4 | bhp.S - enter x86 protected mode 5 | cb.c - c bootloader example and test real mode c pointer. 6 | bh.asm - nasm bootloader code 7 | bh.s - gas bootloader code 8 | 9 | The directory programs are for presentation of MOSUT 10 | (http://code.google.com/p/mosut/ - 作業系統之前的程式 & x86 保護模式 /). 11 | -------------------------------------------------------------------------------- /g1.sh: -------------------------------------------------------------------------------- 1 | file p_kernel.elf.gdb 2 | target remote localhost:1234 3 | #b load_init_boot 4 | #b proc_a 5 | #b romfs_namei 6 | #b romfs_init 7 | #b kernel_main 8 | #b alloc_mem 9 | #b sys_write 10 | #b sys_call 11 | #b init_proc 12 | b do_fork 13 | #b init 14 | #b sys_get_ticks 15 | display proc_table[7].p_flags 16 | display proc_table[3].p_flags 17 | #display ready_process->p_name 18 | display ready_process->name 19 | 20 | #b systask.c:84 21 | -------------------------------------------------------------------------------- /c-bootloader/pc/makefile: -------------------------------------------------------------------------------- 1 | CB_CFLAGS = -fno-stack-protector -std=c99 -march=i686 -ffreestanding -Wall -m32 2 | CB_LDFLAGS = -m elf_i386 3 | 4 | bhp.bin: bhp.elf 5 | objcopy -O binary $< $@ 6 | cb.s: cb.c 7 | gcc $(CB_CFLAGS) -I. -S $< 8 | cb.o: cb.c 9 | gcc $(CB_CFLAGS) -c $< 10 | 11 | bhp.o: bhp.S 12 | gcc -m32 -c bhp.S 13 | 14 | bhp.elf: bhp.o cb.o 15 | ld -m elf_i386 -Tl.ld -o bhp.elf $^ 16 | 17 | clean: 18 | rm -rf *.o *.bin *.elf 19 | -------------------------------------------------------------------------------- /include/k_ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef K_CTYPE_H 2 | #define K_CTYPE_H 3 | 4 | 5 | // a : 0x61 6 | // A : 0x41 7 | // z : 0x7a 8 | // Z : 0x5a 9 | static inline int toupper(int c) 10 | { 11 | if (('a' <= c) && (c <= 'z')) 12 | return (c-0x20); 13 | else 14 | return c; 15 | } 16 | 17 | static inline int tolower(int c) 18 | { 19 | if (('A' <= c) && (c <= 'Z')) 20 | return (c+0x20); 21 | else 22 | return c; 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSCALL_H 2 | #define SYSCALL_H 3 | 4 | #include "process.h" 5 | 6 | // implement in asm_syscall.S 7 | int get_ticks(void); 8 | int set_vga_mode(void); 9 | int write(char *buf, int len); 10 | int sendrec(int function, int src_dest, Message *m); 11 | //int printk(int unused1, int unused2, char *s, Process *proc); 12 | int printk(char *s); 13 | int fork(void); 14 | void exit(int s); 15 | int wait(int *s); 16 | int execl(const char *path); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /c-bootloader/bh.asm: -------------------------------------------------------------------------------- 1 | org 07c00h ; 告訴編譯器程序加載到7c00處 2 | mov ax, cs 3 | mov ds, ax 4 | mov es, ax 5 | call DispStr ; 使用顯示字元串例程 6 | jmp $ ; 無限循環 7 | DispStr: 8 | mov ax, BootMessage 9 | mov bp, ax ; ES:BP = 串位址 10 | mov cx, 16 ; CX = 串長度 11 | mov ax, 01301h ; AH = 13, AL = 01h 12 | mov bx, 000ch ; 頁號為0(BH = 0) 黑底紅字(BL = 0Ch,高亮) 13 | mov dl, 0 14 | int 10h ; 10h 號中斷 15 | ret 16 | BootMessage: db "Hello, NASM!" 17 | times 510-($-$$) db 0 ; 填充剩下的空間,使生成的二進制程式碼恰好為512字節 18 | dw 0xaa55 ; 結束標誌 19 | -------------------------------------------------------------------------------- /include/k_assert.h: -------------------------------------------------------------------------------- 1 | #ifndef K_ASSERT_H 2 | #define K_ASSERT_H 3 | 4 | #include "k_stdio.h" 5 | //#include "syscall.h" 6 | 7 | void assertion_failure(char *exp, char *file, char *base_file, int line); 8 | #define assert(exp) if (exp) ;\ 9 | else assertion_failure(#exp, __FILE__, __BASE_FILE__, __LINE__) 10 | 11 | void panic(const char *fmt, ...); 12 | 13 | static inline void spin(char *func_name) 14 | { 15 | printx("\nspinning in %s ...\n", func_name); 16 | while(1); 17 | } 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/draw_func.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAW_FUNC_H 2 | #define DRAW_FUNC_H 3 | 4 | #include "type.h" 5 | 6 | void draw_box(); 7 | void draw_box_1(int draw_x, int draw_y, int c); 8 | void draw_char(int x, int y, char ch); 9 | void draw_bg(int ox, int oy, u8 *pic_raw_data, int w, int h, u8 *palette); 10 | void draw_256_grid(void); 11 | void draw_point(int x, int y, u8 c); 12 | void set_palette(int index, u8 r, u8 g, u8 b); 13 | void draw_str(int ox, int oy, u8 color); 14 | void draw_8x16_ch(int ox, int oy, u8 ch, u8 color); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /k_assert.c: -------------------------------------------------------------------------------- 1 | #include "k_assert.h" 2 | 3 | void assertion_failure(char *exp, char *file, char *base_file, int line) 4 | { 5 | printx("%c asert(%s) failed: file: %s, base_file: %s, ln%d", MAG_CH_ASSERT, exp, file, base_file, line); 6 | 7 | spin("assertion_failure()"); 8 | __asm__ __volatile__("ud2"); 9 | } 10 | 11 | 12 | void panic(const char *fmt, ...) 13 | { 14 | int i; 15 | char buf[256]; 16 | 17 | char *arg = (char *)(&fmt+1); 18 | int len=s32_vsprintf(buf, fmt, arg); 19 | 20 | printx("%c !!panic!! %s", MAG_CH_PANIC, buf); 21 | 22 | __asm__ __volatile__("ud2"); 23 | } 24 | -------------------------------------------------------------------------------- /c-bootloader/cpp/makefile: -------------------------------------------------------------------------------- 1 | CPPFLAGS = -m32 -g -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector 2 | LDFLAGS = -m elf_i386 3 | 4 | %.dpp: %.cpp 5 | set -e; rm -f $@ ; gcc -MM $(CFLAGS) $< > $@.$$$$ ; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@ ; rm -f $@.$$$$ 6 | 7 | include $(sources:.cpp=.dpp) 8 | 9 | CXX=g++ 10 | 11 | cppb.bin: cppb.elf 12 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 13 | cppb.elf: cppb.o io.o 14 | ld $(LDFLAGS) -static -Tcpp.ld -nostdlib -M -o $@ $^ > cb.elf.map 15 | clean: 16 | rm -rf *.o 17 | -------------------------------------------------------------------------------- /include/tty.h: -------------------------------------------------------------------------------- 1 | #ifndef TTY_H 2 | #define TTY_H 3 | 4 | #include "type.h" 5 | #include "console.h" 6 | 7 | #define TTY_IN_BYTES_NUM 256 8 | #define TTY_NUM 4 9 | 10 | 11 | typedef struct Tty_ 12 | { 13 | u32 inbuf[TTY_IN_BYTES_NUM]; 14 | u32 * inbuf_head; 15 | u32 * inbuf_tail; 16 | int inbuf_count; 17 | u32 ready; 18 | struct Console_ *console; 19 | }Tty; 20 | 21 | void task_tty(void); 22 | int init_tty(Tty *tty); 23 | int put_key(Tty *tty, u32 key); 24 | int select_tty(int tty_index); 25 | 26 | void tty_write(Tty *tty, char *buf, int len); 27 | 28 | extern Tty tty_table[]; 29 | #endif 30 | -------------------------------------------------------------------------------- /include/storage.h: -------------------------------------------------------------------------------- 1 | #ifndef STORAGE_H 2 | #define STORAGE_H 3 | 4 | #include "type.h" 5 | 6 | #define MAX_STORAGE_DEVICE (2) 7 | #define RAMDISK (0) 8 | 9 | typedef unsigned int size_t; 10 | 11 | typedef struct StorageDevice_ 12 | { 13 | u32 start_pos; 14 | u32 sector_size; 15 | u32 storage_size; 16 | int (*dout)(struct StorageDevice_ *sd, void *dest, u32 bias, u32 size); 17 | int (*din)(struct StorageDevice_ *sd, void *dest, u32 bias, u32 size); 18 | }StorageDevice; 19 | 20 | 21 | extern StorageDevice *storage[]; 22 | int register_storage_device(StorageDevice *sd, u32 num); 23 | int ramdisk_driver_init(void); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /c-bootloader/bh.s: -------------------------------------------------------------------------------- 1 | .code16 2 | .text 3 | .global begin 4 | begin: 5 | mov %cs,%ax 6 | mov %ax,%ds 7 | mov %ax,%es 8 | movw $0xb800, %ax 9 | movw %ax, %gs 10 | 11 | 12 | mov $0, %edi /* Destination */ 13 | mov $msg, %esi /* Source */ 14 | 15 | 1: 16 | #cmp $0, %ecx 17 | cmpb $0, (%esi) 18 | jz 2f 19 | movb %ds:(%esi), %al 20 | inc %esi 21 | movb %al, %gs:(%edi) 22 | inc %edi 23 | movb $0xc, %gs:(%edi) 24 | inc %edi 25 | dec %ecx 26 | jmp 1b 27 | 2: 28 | movb $'E', %gs:(160) 29 | jmp . 30 | #msg:.ascii "Hello GAS" 31 | msg: 32 | .asciz "Hello GAS" 33 | #.asciz "Hello World" 34 | .org 510 35 | .word 0xaa55 36 | -------------------------------------------------------------------------------- /include/irq.h: -------------------------------------------------------------------------------- 1 | #ifndef IRQ_H 2 | #define IRQ_H 3 | 4 | #define CLOCK_IRQ 0 5 | #define KEYBOARD_IRQ 1 6 | 7 | #define NR_IRQ 16 8 | 9 | typedef void (*IntHandler)(); 10 | typedef void (*IrqHandler)(); 11 | 12 | extern IrqHandler irq_table[]; 13 | 14 | int disable_irq(int irq_no); 15 | int enable_irq(int irq_no); 16 | 17 | static inline void disable_int(void) 18 | { 19 | __asm__ __volatile__("cli\t\n"); 20 | } 21 | 22 | static inline void enable_int(void) 23 | { 24 | __asm__ __volatile__("sti\t\n"); 25 | } 26 | 27 | static inline void put_irq_handler(int irq, IrqHandler handler) 28 | { 29 | disable_irq(irq); 30 | irq_table[irq] = handler; 31 | } 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /vga/makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -O0 2 | #ASFLAGS = --32 3 | #LDFLAGS = -m elf_i386 4 | 5 | ifdef COMSPEC 6 | # in windows 7 | include ..\rule.mk 8 | else 9 | include ../rule.mk 10 | endif 11 | 12 | sources = draw_func.c font_rawdata.c 13 | include $(sources:.c=.d) 14 | 15 | 16 | set_mode_p.o: set_mode_p.S 17 | gcc $(CFLAGS) -o $@ -c $< 18 | 19 | #draw_func.o: draw_func.c draw_func.h ../include/type.h 20 | # gcc $(CFLAGS) -o $@ -c $< 21 | 22 | 23 | set_mode.bin: set_mode.elf 24 | objcopy -O binary $< $@ 25 | set_mode.o: set_mode.S 26 | gcc -o $@ -c $< 27 | 28 | set_mode.elf: set_mode.o 29 | ld -Tas.ld -o $@ $< 30 | 31 | 32 | -------------------------------------------------------------------------------- /vga/as.ld: -------------------------------------------------------------------------------- 1 | ENTRY(begin); 2 | SECTIONS 3 | { 4 | . = 0x7C00; 5 | .text : AT(0x7C00) 6 | { 7 | _text = .; 8 | *(.text); 9 | _text_end = .; 10 | } 11 | .data : 12 | { 13 | _data = .; 14 | *(.bss); 15 | *(.bss*); 16 | *(.data); 17 | *(.rodata*); 18 | *(COMMON) 19 | _data_end = .; 20 | } 21 | .sig : AT(0x7DFE) 22 | { 23 | SHORT(0xaa55); 24 | } 25 | /DISCARD/ : 26 | { 27 | *(.note*); 28 | *(.iplt*); 29 | *(.igot*); 30 | *(.rel*); 31 | *(.comment); 32 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /c-bootloader/pc/l.ld: -------------------------------------------------------------------------------- 1 | ENTRY(main); 2 | SECTIONS 3 | { 4 | . = 0x7C00; 5 | .text : AT(0x7C00) 6 | { 7 | _text = .; 8 | *(.text); 9 | _text_end = .; 10 | } 11 | .data : 12 | { 13 | _data = .; 14 | *(.bss); 15 | *(.bss*); 16 | *(.data); 17 | *(.rodata*); 18 | *(COMMON) 19 | _data_end = .; 20 | } 21 | .sig : AT(0x7DFE) 22 | { 23 | SHORT(0xaa55); 24 | } 25 | /DISCARD/ : 26 | { 27 | *(.note*); 28 | *(.iplt*); 29 | *(.igot*); 30 | *(.rel*); 31 | *(.comment); 32 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /include/kl_global.h: -------------------------------------------------------------------------------- 1 | //kl meads kernel loader 2 | #ifndef KL_GLOBAL_H 3 | #define KL_GLOBAL_H 4 | 5 | #define KERNEL_ES 0x0050 6 | #define KERNEL_INFO (KERNEL_ES << 4 | LOAD_KERNEL_OFFSET) 7 | #define IMAGE_SIZE 8192 8 | #define BLOCK_SIZE 512 9 | #define READ_FAT_ADDR (0x3000) // original is 0x2000, but will overwrite bss (variable bpb), so change to 0x3000 10 | #define IMAGE_LMA (0x4000) 11 | //#define LOAD_KERNEL_OFFSET (0x0) 12 | #define LOAD_KERNEL_OFFSET (0x200000) 13 | //#define IMAGE_LMA 0x8000 14 | #define IMAGE_ENTRY 0x800c 15 | #define buf_addr_val (*(u8 volatile*(IMAGE_LMA))) 16 | #define LOAD_KERNEL_ADDR 0x300000 // in big real mode, copy buffer (load by int 0x13) to the address 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /c-bootloader/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(main); 2 | SECTIONS 3 | { 4 | . = 0x7C00; 5 | .text : AT(0x7C00) 6 | { 7 | _text = .; 8 | *(.text); 9 | _text_end = .; 10 | } 11 | .data : 12 | { 13 | _data = .; 14 | *(.bss); 15 | *(.bss*); 16 | *(.data); 17 | *(.rodata*); 18 | *(COMMON) 19 | _data_end = .; 20 | } 21 | .sig : AT(0x7DFE) 22 | { 23 | SHORT(0xaa55); 24 | } 25 | /DISCARD/ : 26 | { 27 | *(.note*); 28 | *(.iplt*); 29 | *(.igot*); 30 | *(.rel*); 31 | *(.comment); 32 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /c-bootloader/linker_dos.ld: -------------------------------------------------------------------------------- 1 | ENTRY(main); 2 | SECTIONS 3 | { 4 | . = 0x0100; 5 | .text : 6 | { 7 | _text = .; 8 | *(.text); 9 | _text_end = .; 10 | } 11 | .data : 12 | { 13 | _data = .; 14 | *(.bss); 15 | *(.bss*); 16 | *(.data); 17 | *(.rodata*); 18 | *(COMMON) 19 | _data_end = .; 20 | } 21 | /* .sig : AT(0x7DFE) 22 | { 23 | SHORT(0xaa55); 24 | } */ 25 | /DISCARD/ : 26 | { 27 | *(.note*); 28 | *(.iplt*); 29 | *(.igot*); 30 | *(.rel*); 31 | *(.comment); 32 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /c-bootloader/as.ld: -------------------------------------------------------------------------------- 1 | ENTRY(begin); 2 | SECTIONS 3 | { 4 | . = 0x7C00; 5 | .text : AT(0x7C00) 6 | { 7 | _text = .; 8 | *(.text); 9 | _text_end = .; 10 | } 11 | .data : 12 | { 13 | _data = .; 14 | *(.bss); 15 | *(.bss*); 16 | *(.data); 17 | *(.rodata*); 18 | *(COMMON) 19 | _data_end = .; 20 | } 21 | /* 22 | .sig : AT(0x7DFE) 23 | { 24 | SHORT(0xaa55); 25 | } 26 | */ 27 | /DISCARD/ : 28 | { 29 | *(.note*); 30 | *(.iplt*); 31 | *(.igot*); 32 | *(.rel*); 33 | *(.comment); 34 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /c-bootloader/l.ld: -------------------------------------------------------------------------------- 1 | /* for cb.c */ 2 | ENTRY(WinMain); 3 | SECTIONS 4 | { 5 | . = 0x7C00; 6 | .text : AT(0x7C00) 7 | { 8 | _text = .; 9 | *(.text); 10 | _text_end = .; 11 | } 12 | .data : 13 | { 14 | _data = .; 15 | *(.bss); 16 | *(.bss*); 17 | *(.data); 18 | *(.rodata*); 19 | *(COMMON) 20 | _data_end = .; 21 | } 22 | .sig : AT(0x7DFE) 23 | { 24 | SHORT(0xaa55); 25 | } 26 | /DISCARD/ : 27 | { 28 | *(.note*); 29 | *(.iplt*); 30 | *(.igot*); 31 | *(.rel*); 32 | *(.comment); 33 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /c-bootloader/cpp/global_object/makefile: -------------------------------------------------------------------------------- 1 | #CPPFLAGS = -m32 -g -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector 2 | CPPFLAGS = -m32 -g -Wall -Wextra -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector 3 | LDFLAGS = -m elf_i386 4 | 5 | %.dpp: %.cpp 6 | set -e; rm -f $@ ; gcc -MM $(CFLAGS) $< > $@.$$$$ ; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@ ; rm -f $@.$$$$ 7 | 8 | include $(sources:.cpp=.dpp) 9 | 10 | CXX=g++ 11 | 12 | cppb.bin: cppb.elf 13 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 14 | cppb.elf: cppb.o io.o 15 | ld $(LDFLAGS) -static -Tcpp.ld -nostdlib -M -o $@ $^ > cb.elf.map 16 | clean: 17 | rm -rf *.o 18 | -------------------------------------------------------------------------------- /apps/echo.c: -------------------------------------------------------------------------------- 1 | #include "k_stdio.h" 2 | 3 | int main(int argc, const char *argv[]) 4 | { 5 | #if 0 6 | *((unsigned char *)(0xb8000+160*22+0)) = 'e'; 7 | *((unsigned char *)(0xb8000+160*22+1)) = 0x14; 8 | *((unsigned char *)(0xb8000+160*22+2)) = 'c'; 9 | *((unsigned char *)(0xb8000+160*22+3)) = 0x94; 10 | *((unsigned char *)(0xb8000+160*22+4)) = 'h'; 11 | *((unsigned char *)(0xb8000+160*22+5)) = 0x0f; 12 | *((unsigned char *)(0xb8000+160*22+6)) = 'o'; 13 | *((unsigned char *)(0xb8000+160*22+7)) = 0x0c; 14 | #endif 15 | //s32_printf("I am app\r\n"); 16 | 17 | 18 | app_print("I am echo app"); 19 | #if 1 20 | for (int i=0 ; i < 10000 ; ++i) 21 | for (int j=0 ; j < 10000 ; ++j) 22 | ; 23 | #endif 24 | 25 | return 678; 26 | } 27 | -------------------------------------------------------------------------------- /include/vfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ref 一步步寫嵌入式操作系統, chapter 7 3 | * 4 | */ 5 | #ifndef VFS_H 6 | #define VFS_H 7 | 8 | #include "type.h" 9 | #include "storage.h" 10 | 11 | #define MAX_SUPER_BLOCK 8 12 | #define ROMFS 0 13 | 14 | 15 | struct SuperBlock_; 16 | 17 | typedef struct INode_ 18 | { 19 | char *fn_name; 20 | u32 flags; 21 | u32 dsize; 22 | u32 daddr; 23 | struct SuperBlock_ *sb; 24 | }INode; 25 | 26 | typedef struct SuperBlock_ 27 | { 28 | INode *(*namei)(struct SuperBlock_ *sb, char *p); 29 | u32 (*get_daddr)(INode *); 30 | StorageDevice *device; 31 | char *fs_name; 32 | }SuperBlock; 33 | 34 | int register_file_system(SuperBlock *type, u32 id); 35 | int unregister_file_system(SuperBlock *type, u32 id); 36 | 37 | extern SuperBlock *fs_type[]; 38 | #endif 39 | -------------------------------------------------------------------------------- /c-bootloader/cpp/cppb.cpp: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | #include "io.h" 3 | 4 | /* 5 | * c bootloader 6 | */ 7 | 8 | //#define POINTER_TEST 9 | 10 | 11 | int bbb=0; // test bss section 12 | 13 | extern "C" void WinMain(void) 14 | { 15 | __asm__ ("mov %cs, %ax\n"); 16 | __asm__ ("mov %ax, %ds\n"); 17 | __asm__ ("mov %ax, %ss\n"); 18 | __asm__ ("mov $0xfff0, %sp\n"); 19 | { 20 | Io io; 21 | io.print("hello cpp class\r\n"); 22 | } 23 | #if 0 24 | unsigned char *vb = (unsigned char *)0xb8000; 25 | *vb = 'A'; 26 | *(unsigned char *)0xb8001 = 0xc; 27 | *(unsigned char *)0xb8002 = 'B'; 28 | *(unsigned char *)0xb8003 = 0x9; 29 | *(unsigned char *)0xb8004 = '@'; 30 | *(unsigned char *)0xb8005 = 0xc; 31 | #endif 32 | while(1); 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /bss.lds: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x7c00; 6 | .text : 7 | { 8 | *(.text) 9 | } 10 | .= ALIGN(32); 11 | 12 | .data : 13 | { 14 | *(.data) 15 | } 16 | 17 | .= ALIGN(32); 18 | __bss_start__ =.; 19 | .bss : 20 | { 21 | *(.bss) 22 | } 23 | __bss_end__ = .; 24 | 25 | .sig : AT(0x7DFE) 26 | { 27 | SHORT(0xaa55); 28 | } 29 | /* 30 | .asig : AT(0x7e50) 31 | { 32 | SHORT(0xefab); 33 | } 34 | .bsig : AT(0x7f50) 35 | { 36 | SHORT(0xefab); 37 | } 38 | */ 39 | /DISCARD/ : 40 | { 41 | *(.note*); 42 | *(.iplt*); 43 | *(.igot*); 44 | *(.rel*); 45 | *(.comment); 46 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /clock.c: -------------------------------------------------------------------------------- 1 | #include "clock.h" 2 | #include "type.h" 3 | #include "process.h" 4 | 5 | char* s32_itoa(int n, char* str, int radix); 6 | void s32_print(const u8 *s, u8 *vb); 7 | void clear_line(u8 line_no); 8 | void loop_delay(int time); 9 | 10 | extern int k_reenter; 11 | extern u8 *cur_vb; 12 | 13 | u32 ticks; 14 | 15 | void clock_handler(int irq) 16 | { 17 | ++ticks; 18 | static u16 p = 4; 19 | //s32_print("@", (u8*)(0xb8000+p*2)); 20 | //s32_print("@", cur_vb); 21 | 22 | ++p; 23 | if (k_reenter != 0) 24 | { 25 | //s32_print("!", (u8*)(0xb8000+p*2)); 26 | //s32_print("!", cur_vb); 27 | return; 28 | } 29 | 30 | schedule(); 31 | #if 0 32 | ++ready_process; 33 | if (ready_process >= &proc_table[NR_TASKS + NR_PROCS]) 34 | ready_process = proc_table; 35 | #endif 36 | } 37 | -------------------------------------------------------------------------------- /include/k_stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef K_STDLIB_H 2 | #define K_STDLIB_H 3 | 4 | #include "type.h" 5 | 6 | // bochs magic break point 7 | #define BOCHS_MB __asm__ __volatile__("xchg %bx, %bx"); 8 | 9 | // sign version 10 | char* s32_itoa_s(int n, char* str, int radix); 11 | 12 | // unsign version 13 | char* s32_itoa(u32 n, char* str, int radix); 14 | 15 | static inline void asm_set_es(u16 es_v) 16 | { 17 | __asm__ __volatile__ 18 | ( 19 | "mov %%ax, %%es\n" 20 | : // output 21 | : "a"(es_v)// input 22 | ); 23 | } 24 | 25 | static inline u16 asm_get_es(void) 26 | { 27 | u16 es_v=0; 28 | __asm__ __volatile__ 29 | ( 30 | "mov %%es, %%ax\n" 31 | : "=a"(es_v)// output 32 | ); 33 | return es_v; 34 | } 35 | 36 | int get_kernel_info(u32 * b, u32 * l); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /script/cp2img.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # copy needed files to floppy image. 3 | 4 | #make c_init_by_boot_loader.bin 5 | make kloaderp.bin 6 | make p_kernel.elf 7 | sudo mount -o loop boot.img /mnt/ 8 | #sudo cp kloader.bin /mnt/loader.bin 9 | sudo cp -v kernel_loader/kloaderp.bin /mnt/loader.bin 10 | #sudo cp kloader.bin /mnt/test.bin 11 | sudo cp kernel.bin /mnt/ 12 | sudo cp kernel.elf /mnt/ 13 | sudo cp -v p_kernel.elf /mnt/ 14 | sudo cp rom.fs /mnt/ 15 | sudo cp /home/descent/git/write_os/src/chapter3/1.5/idt.com /mnt/ 16 | sudo cp /home/descent/git/write_os/src/chapter3/1.5/idt.com.elf /mnt/idt.elf 17 | #sudo cp c_init_by_boot_loader.bin /mnt/loader.bin 18 | sudo ls -l /mnt 19 | sudo umount /mnt 20 | 21 | #sudo mount -o loop dos6.22_data.img /mnt/ 22 | #sudo cp c_init_by_boot_loader.bin /mnt/c.com 23 | #sudo umount /mnt 24 | -------------------------------------------------------------------------------- /ut/ut.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test some function 3 | * 4 | */ 5 | 6 | #include "k_stdio.h" 7 | #include 8 | 9 | void panic(const char *fmt, ...) 10 | { 11 | char buf[256]; 12 | char *arg = (char *)(&fmt+1); 13 | 14 | u32 arg_content = *((int *)arg); 15 | 16 | int len=s32_vsprintf(buf, fmt, arg); 17 | //int len=s32_sprintf(buf, fmt, arg); 18 | printf("%d ## %s", len, buf); 19 | //printf("%d\n", len); 20 | } 21 | 22 | 23 | int main(int argc, const char *argv[]) 24 | { 25 | char buf[256]; 26 | for (int i=0 ; i < 256 ; ++i) 27 | buf[i] = 'A'; 28 | int hi=0x98ef; 29 | int i=53; 30 | int len = s32_sprintf(buf, "%d %x %s\n", i, hi, "testcc"); 31 | //printf("%d ## %s", len, buf); 32 | //panic("%d %x %s\n", i, hi, "panic"); 33 | panic("%d %x %s\n", i, hi, "panic"); 34 | //printf("%d ## %s", len, buf); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /include/endian.h: -------------------------------------------------------------------------------- 1 | #ifndef ENDIAN_H 2 | #define ENDIAN_H 3 | 4 | #include "type.h" 5 | 6 | #define swap(a, b) \ 7 | {\ 8 | a^=b; \ 9 | b^=a; \ 10 | a^=b;\ 11 | } 12 | 13 | 14 | typedef union U_ 15 | { 16 | struct 17 | { 18 | u8 c0; 19 | u8 c1; 20 | u8 c2; 21 | u8 c3; 22 | } ch; 23 | u32 ui; 24 | }U; 25 | 26 | // ref: 27 | // #include 28 | // man endian 29 | 30 | static inline u32 be32tole32(u32 big_endian_32bits) 31 | { 32 | U u; 33 | u.ui = big_endian_32bits; 34 | swap(u.ch.c0, u.ch.c3); 35 | swap(u.ch.c1, u.ch.c2); 36 | return u.ui; 37 | } 38 | 39 | static inline u32 le32tobe32(u32 host_32bits) 40 | { 41 | U u; 42 | u.ui = host_32bits; 43 | #if 1 44 | swap(u.ch.c0, u.ch.c3); 45 | swap(u.ch.c1, u.ch.c2); 46 | //printf("u: %x\n", u.ui); 47 | #endif 48 | return u.ui; 49 | } 50 | 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /bss_dos.lds: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x100; 6 | .text : 7 | { 8 | *(.text) 9 | } 10 | .= ALIGN(32); 11 | .rodata : 12 | { 13 | *(.rodata) 14 | } 15 | .= ALIGN(32); 16 | 17 | .data : 18 | { 19 | *(.data) 20 | } 21 | 22 | /* .= 0xeffa; */ 23 | .= ALIGN(32); 24 | __bss_start__ =.; 25 | .bss : 26 | { 27 | *(.bss) 28 | } 29 | __bss_end__ = .; 30 | 31 | /* 32 | .sig : AT(0x7DFE) 33 | { 34 | SHORT(0xaa55); 35 | } 36 | .asig : AT(0x7e50) 37 | { 38 | SHORT(0xefab); 39 | } 40 | .bsig : AT(0x7f50) 41 | { 42 | SHORT(0xefab); 43 | } 44 | */ 45 | /DISCARD/ : 46 | { 47 | *(.note*); 48 | *(.iplt*); 49 | *(.igot*); 50 | *(.rel*); 51 | *(.comment); 52 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /apps/makefile: -------------------------------------------------------------------------------- 1 | echo.bin: echo 2 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 3 | echo: start.o echo.o 4 | #../syscall.o 5 | #../asm_func.o ../clock.o ../k_stdlib.o ../process.o ../storage.o ../systask.o ../asm_syscall.o ../k_assert.o ../p_kernel.o ../start.o 6 | #ld -m elf_i386 -Ttext 0x1000 -o echo $^ 7 | ld -m elf_i386 -Ttext 0x1000 -e cstart -o echo start.o echo.o ../p_kernel.o ../io/k_stdio.o ../asm_func.o ../asm_syscall.o ../vga/set_mode_p.o ../vga/draw_func.o ../vga/font_rawdata.o ../tty/tty.o ../tty/keyboard.o ../tty/console.o ../clock.o ../start.o ../process.o ../storage.o ../syscall.o ../io/k_stdio_k.o ../k_assert.o ../systask.o ../mm/mm.o ../k_stdlib.o ../fs/romfs.o ../fs/vfs.o && cp echo echo.gdb && strip echo 8 | echo.o: echo.c 9 | gcc -std=c99 -g -I../include -m32 -c echo.c 10 | start.o: start.S 11 | gcc -g -m32 -c start.S 12 | 13 | clean: 14 | rm -rf *.o echo 15 | -------------------------------------------------------------------------------- /kernel_loader/klp.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x100; 6 | .text : 7 | { 8 | *(.text) 9 | } 10 | .= ALIGN(32); 11 | .rodata : 12 | { 13 | *(.rodata) 14 | } 15 | .= ALIGN(32); 16 | 17 | .data : 18 | { 19 | *(.data) 20 | } 21 | 22 | /* .= 0xeffa; */ 23 | .= ALIGN(32); 24 | __bss_start__ =.; 25 | .bss : 26 | { 27 | *(.bss) 28 | } 29 | __bss_end__ = .; 30 | 31 | /* 32 | .sig : AT(0x7DFE) 33 | { 34 | SHORT(0xaa55); 35 | } 36 | .asig : AT(0x7e50) 37 | { 38 | SHORT(0xefab); 39 | } 40 | .bsig : AT(0x7f50) 41 | { 42 | SHORT(0xefab); 43 | } 44 | */ 45 | /DISCARD/ : 46 | { 47 | *(.note*); 48 | *(.iplt*); 49 | *(.igot*); 50 | *(.rel*); 51 | *(.comment); 52 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /tty/makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -O0 2 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -I../include 3 | #ASFLAGS = --32 -g 4 | #LDFLAGS = -m elf_i386 5 | 6 | ifdef COMSPEC 7 | # in windows 8 | include ..\rule.mk 9 | else 10 | include ../rule.mk 11 | endif 12 | 13 | #protected_code.e: protected_code.c 14 | # gcc $(CFLAGS) -E -o $@ -S $< 15 | 16 | 17 | 18 | %.d: %.c 19 | set -e; rm -f $@ ; gcc -MM $(CFLAGS) $< > $@.$$$$ ; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@ ; rm -f $@.$$$$ 20 | 21 | sources = keyboard.c console.c tty.c 22 | include $(sources:.c=.d) 23 | 24 | 25 | # ref: http://www.gnu.org/software/make/manual/make.html 26 | #%.d: %.c 27 | #@set -e; rm -f $@; \ 28 | #$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ 29 | #sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ 30 | #rm -f $@.$$$$ 31 | 32 | .PHONE: clean 33 | 34 | clean: 35 | rm -rf *.o *.elf *.d *.e 36 | -------------------------------------------------------------------------------- /include/io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_H 2 | #define IO_H 3 | 4 | #include "type.h" 5 | 6 | static inline u8 io_in8(u16 port) 7 | { 8 | 9 | // ref: http://wiki.osdev.org/Inline_Assembly/Examples 10 | u8 ret; 11 | __asm__ volatile( "inb %1, %0" 12 | : "=a"(ret) : "Nd"(port) ); 13 | return ret; 14 | } 15 | 16 | 17 | static inline 18 | void io_out8(u16 port, u8 data) 19 | { 20 | // outb %al, $0x92 21 | // N: "N" : Constant in range 0 to 255 (for out instruction). 22 | // ref: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s6 23 | __asm__ volatile("outb %0, %1" 24 | : : "a"(data), "Nd"(port) ); 25 | __asm__ volatile("nop\t\n"); 26 | __asm__ volatile("nop\t\n"); 27 | } 28 | 29 | static inline 30 | void io_out16(u16 port, u16 data) 31 | { 32 | __asm__ volatile("outw %0, %1" 33 | : : "a"(data), "Nd"(port) ); 34 | __asm__ volatile("nop\t\n"); 35 | __asm__ volatile("nop\t\n"); 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /k.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x100000; 6 | .text : 7 | { 8 | *(.text) 9 | } 10 | .= ALIGN(32); 11 | .rodata : 12 | { 13 | *(.rodata) 14 | } 15 | .= ALIGN(32); 16 | 17 | .data : 18 | { 19 | *(.data) 20 | } 21 | 22 | /* .= 0xeffa; */ 23 | .= ALIGN(32); 24 | __bss_start__ =.; 25 | .bss : 26 | { 27 | *(.bss) 28 | } 29 | __bss_end__ = .; 30 | 31 | . = ALIGN(32); 32 | __romfs_start__ =.; 33 | .romfs.data : 34 | { 35 | *(.romfs.data) 36 | } 37 | __romfs_end__ = .; 38 | 39 | /* 40 | .sig : AT(0x7DFE) 41 | { 42 | SHORT(0xaa55); 43 | } 44 | .asig : AT(0x7e50) 45 | { 46 | SHORT(0xefab); 47 | } 48 | .bsig : AT(0x7f50) 49 | { 50 | SHORT(0xefab); 51 | } 52 | */ 53 | /DISCARD/ : 54 | { 55 | *(.note*); 56 | *(.iplt*); 57 | *(.igot*); 58 | *(.rel*); 59 | *(.comment); 60 | /* add any unwanted sections spewed out by your version of gcc and flags here */ 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /asm_func.S: -------------------------------------------------------------------------------- 1 | #include "io_port.h" 2 | 3 | .global disable_irq 4 | disable_irq: 5 | mov 4(%esp), %ecx 6 | pushf 7 | cli 8 | mov $1, %ah 9 | rol %cl, %ah 10 | cmp $8, %cl 11 | jae disable_8 12 | disable_0: 13 | in $INT_M_CTLMASK, %al 14 | test %ah, %al 15 | jnz dis_already 16 | or %ah, %al 17 | outb %al, $INT_M_CTLMASK 18 | popf 19 | mov $1, %eax 20 | retl 21 | disable_8: 22 | in $INT_S_CTLMASK, %al 23 | test %ah, %al 24 | jnz dis_already 25 | or %ah, %al 26 | outb %al, $INT_M_CTLMASK 27 | popf 28 | mov $1, %eax 29 | retl 30 | dis_already: 31 | popf 32 | xor %eax, %eax 33 | retl 34 | 35 | .global enable_irq 36 | enable_irq: 37 | mov 4(%esp), %ecx 38 | pushf 39 | cli 40 | mov $~1, %ah 41 | rol %cl, %ah 42 | cmp $8, %cl 43 | jae enable_8 44 | enable_0: 45 | in $INT_M_CTLMASK, %al 46 | and %ah, %al 47 | outb %al, $INT_M_CTLMASK 48 | popf 49 | retl 50 | enable_8: 51 | in $INT_S_CTLMASK, %al 52 | and %ah, %al 53 | outb %al, $INT_M_CTLMASK 54 | popf 55 | retl 56 | -------------------------------------------------------------------------------- /c-bootloader/cpp/cpp.ld: -------------------------------------------------------------------------------- 1 | /* for cb.c */ 2 | ENTRY(WinMain); 3 | SECTIONS 4 | { 5 | 6 | . = 0x7C00; 7 | .text : AT(0x7C00) 8 | { 9 | *(.text) 10 | *(.gnu.linkonce.t*) 11 | } 12 | 13 | .rodata : 14 | { 15 | start_ctors = .; 16 | *(SORT(.ctors.*)) /* Note the "SORT" */ 17 | end_ctors = .; 18 | 19 | start_dtors = .; 20 | *(SORT(.dtors.*)) 21 | end_dtors = .; 22 | 23 | *(.rodata*) 24 | *(.gnu.linkonce.r*) 25 | } 26 | 27 | .data : 28 | { 29 | *(.data) 30 | *(.gnu.linkonce.d*) 31 | } 32 | 33 | .bss : 34 | { 35 | sbss = .; 36 | *(COMMON) 37 | *(.bss) 38 | *(.gnu.linkonce.b*) 39 | ebss = .; 40 | } 41 | 42 | .sig : AT(0x7DFE) 43 | { 44 | SHORT(0xaa55); 45 | } 46 | /DISCARD/ : 47 | { 48 | *(.comment) 49 | *(.eh_frame) /* discard this, unless you are implementing runtime support for C++ exceptions. */ 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /c-bootloader/mkimg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #if [ "$1" == "" ] ; then 4 | # echo "usage: $0 a.bin" 5 | # exit -1 6 | #fi 7 | 8 | FN=./floppy.img 9 | BIN="" 10 | 11 | # ref: http://wiki.bash-hackers.org/howto/getopts_tutorial 12 | while getopts "b:d:" opt; do 13 | case $opt in 14 | b) 15 | echo $OPTARG 16 | BIN=$OPTARG 17 | ;; 18 | d) 19 | echo $OPTARG 20 | FN=$OPTARG 21 | ;; 22 | \?) 23 | echo "usage: $0 -b bin -d dev" 24 | echo "ex: $0 -b boot.bin -d boot.img" 25 | echo "ex: $0 -b boot.bin -d /dev/sdz" 26 | exit 0 27 | ;; 28 | *) 29 | echo "xx invalid" 30 | exit 0 31 | ;; 32 | esac 33 | 34 | done 35 | 36 | if [ -e $FN ] 37 | then 38 | echo "$FN exists" 39 | else 40 | echo "$FN doesn't exist, create $FN" 41 | dd if=/dev/zero of=$FN skip=1 seek=1 bs=512 count=2879 42 | fi 43 | 44 | echo "" 45 | 46 | 47 | if [ -n "$BIN" ]; then 48 | echo "write $BIN to $FN" 49 | dd if=$BIN of=$FN bs=1 count=512 conv=notrunc 50 | fi 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /k_stdlib.c: -------------------------------------------------------------------------------- 1 | #include "k_stdlib.h" 2 | #include "k_string.h" 3 | #include "kl_global.h" 4 | #include "elf.h" 5 | 6 | int get_kernel_info(u32 * b, u32 * l) 7 | { 8 | Elf32Ehdr *elf_header = (Elf32Ehdr*)KERNEL_INFO; 9 | u32 kaddr = KERNEL_INFO; 10 | if (s_memcmp(elf_header->e_ident, ELFMAG, SELFMAG) != 0) 11 | { 12 | s32_print("not elf", (u8*)(0xb8000+160*24 + 12*2)); 13 | return -1; 14 | } 15 | else 16 | { 17 | s32_print("find elf", (u8*)(0xb8000+160*24 + 12*2)); 18 | } 19 | 20 | *b = ~0; 21 | unsigned int t = 0; 22 | int i; 23 | for (i = 0; i < elf_header->e_shnum; i++) 24 | { 25 | Elf32_Shdr* section_header = (Elf32_Shdr*)(KERNEL_INFO + elf_header->e_shoff + i * elf_header->e_shentsize); 26 | 27 | if (section_header->sh_flags & SHF_ALLOC) 28 | { 29 | int bottom = section_header->sh_addr; 30 | int top = section_header->sh_addr + section_header->sh_size; 31 | 32 | if (*b > bottom) 33 | *b = bottom; 34 | if (t < top) 35 | t = top; 36 | } 37 | } 38 | *l = t - *b - 1; 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /c-bootloader/cb.c: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | /* 3 | * c bootloader 4 | */ 5 | 6 | //#define POINTER_TEST 7 | 8 | void main(const char *s); 9 | 10 | int bbb=0; // test bss section 11 | 12 | void WinMain(void) 13 | { 14 | __asm__ ("mov %cs, %ax\n"); 15 | __asm__ ("mov %ax, %ds\n"); 16 | __asm__ ("mov %ax, %ss\n"); 17 | __asm__ ("mov $0xff00, %sp\n"); 18 | #ifdef POINTER_TEST 19 | unsigned char *vb = (unsigned char *)0xb8000; 20 | *vb = 'A'; 21 | *(unsigned char *)0xb8001 = 0xc; 22 | *(unsigned char *)0xb8002 = 'B'; 23 | *(unsigned char *)0xb8003 = 0xc; 24 | #else 25 | main("hello cc"); 26 | unsigned char *vb = (unsigned char *)0xb8000; 27 | *vb = 'A'; 28 | *(unsigned char *)0xb8001 = 0xc; 29 | *(unsigned char *)0xb8002 = 'B'; 30 | *(unsigned char *)0xb8003 = 0x9; 31 | *(unsigned char *)0xb8004 = '@'; 32 | *(unsigned char *)0xb8005 = 0xc; 33 | #endif 34 | while(1); 35 | } 36 | 37 | #ifndef POINTER_TEST 38 | void main(const char *s) 39 | { 40 | while(*s) 41 | { 42 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 43 | s++; 44 | } 45 | } 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /include/vga.h: -------------------------------------------------------------------------------- 1 | #ifndef VGA_H 2 | #define VGA_H 3 | 4 | // ref: 5 | // http://www.stanford.edu/class/cs140/projects/pintos/specs/freevga/vga/portidx.htm 6 | // http://www.stanford.edu/class/cs140/projects/pintos/specs/freevga/vga/crtcreg.htm 7 | 8 | // CRT Controller Registers 9 | #define CRTC_ADDR 0x3D4 10 | #define CRTC_DATA 0x3D5 11 | 12 | #define START_ADDR_H 0xC /* reg index of video mem start addr (MSB) */ 13 | #define START_ADDR_L 0xD /* reg index of video mem start addr (LSB) */ 14 | #define CURSOR_H 0xE /* reg index of cursor position (MSB) */ 15 | #define CURSOR_L 0xF /* reg index of cursor position (LSB) */ 16 | 17 | 18 | // ref: http://www.2cto.com/kf/201111/109728.html 19 | #define PALETTE_MASK 0x3c6 //调色板屏蔽寄存器端口,放入0xff可以通过调色板索引寄存器0x3c7和0x3c8访问你希望的寄存器 20 | #define PALETTE_REGISTER_RD 0x3c7 //读颜色寄存器端口 21 | #define PALETTE_REGISTER_WR 0x3c8 //写颜色寄存器端口 22 | #define PALETTE_DATA 0x3c9 //调色板数据寄存器端口 23 | 24 | #define V_MEM_BASE 0xB8000 25 | #define V_MEM_SIZE 0x8000 26 | #define SCR_WIDTH 80 27 | #define RED_CHAR 0x9 28 | #define GRAY_CHAR 0x7 29 | 30 | void switch_vga_mode(void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /c-bootloader/cpp/global_object/cpp.ld: -------------------------------------------------------------------------------- 1 | /* for cb.c */ 2 | ENTRY(WinMain); 3 | SECTIONS 4 | { 5 | 6 | . = 0x100; 7 | .text : AT(0x7C00) 8 | { 9 | *(.text) 10 | *(.gnu.linkonce.t*) 11 | } 12 | .ctors : 13 | { 14 | start_ctors = .; _start_ctors = .; __start_ctors = .; 15 | *(.ctor*) 16 | end_ctors = .; _end_ctors = .; __end_ctors = .; 17 | . = ALIGN(0x1000); 18 | } 19 | .dtors : 20 | { 21 | start_dtors = .; _start_dtors = .; __start_dtors = .; 22 | *(.dtor*) 23 | end_dtors = .; _end_dtors = .; __end_dtors = .; 24 | . = ALIGN(0x1000); 25 | } 26 | 27 | .rodata : 28 | { 29 | 30 | 31 | *(.rodata*) 32 | *(.gnu.linkonce.r*) 33 | } 34 | 35 | .data : 36 | { 37 | *(.data) 38 | *(.gnu.linkonce.d*) 39 | } 40 | 41 | .bss : 42 | { 43 | sbss = .; 44 | *(COMMON) 45 | *(.bss) 46 | *(.gnu.linkonce.b*) 47 | ebss = .; 48 | } 49 | 50 | /DISCARD/ : 51 | { 52 | *(.comment) 53 | *(.eh_frame) /* discard this, unless you are implementing runtime support for C++ exceptions. */ 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /c-bootloader/vbr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A simple bootloader skeleton for x86, using gcc. 3 | * 4 | * Prashant Borole (boroleprashant at Google mail) 5 | * */ 6 | 7 | /* XXX these must be at top */ 8 | #include "code16gcc.h" 9 | __asm__ ("jmpl $0, $main\n"); 10 | //unsigned char stack[]={0x1,2,3,4}; 11 | 12 | #define __NOINLINE __attribute__((noinline)) 13 | #define __REGPARM __attribute__ ((regparm(3))) 14 | #define __NORETURN __attribute__((noreturn)) 15 | 16 | /* BIOS interrupts must be done with inline assembly */ 17 | void __NOINLINE __REGPARM print(const char *s){ 18 | while(*s){ 19 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 20 | s++; 21 | } 22 | } 23 | /* and for everything else you can use C! Be it traversing the filesystem, or verifying the kernel image etc.*/ 24 | 25 | // setup stack address to 0x7c00 - 0x200 = 0x7a00 26 | // %ss = 0x7a00, %esp = 0 27 | void __NORETURN main(){ 28 | __asm__ ("mov %cs, %ax\n"); 29 | __asm__ ("mov %ax, %ds\n"); 30 | __asm__ ("mov $0x07a0, %ax\n"); 31 | __asm__ ("mov %ax, %ss\n"); 32 | __asm__ ("mov $0, %esp\n"); 33 | print("woo hoo!\r\n:)"); 34 | while(1); 35 | } 36 | -------------------------------------------------------------------------------- /include/romfs.h: -------------------------------------------------------------------------------- 1 | #ifndef ROMFS_H 2 | #define ROMFS_H 3 | 4 | #define HARD_LINK 0 5 | #define DIRECTORY 1 6 | #define REGULAR_FILE 2 7 | #define SYMBOLIC_LINK 3 8 | #define BLOCK_DEVICE 4 9 | #define CHAR_DEVICE 5 10 | #define SOCKET 6 11 | #define FIFO 7 12 | 13 | int romfs_init(void); 14 | 15 | typedef struct RomFsHeader_ 16 | { 17 | union 18 | { 19 | u8 id_str[8]; 20 | struct 21 | { 22 | u32 nextfh; 23 | u32 spec; 24 | }header8; 25 | }u; 26 | u32 size; 27 | u32 checksum; 28 | //u8 *fn; // not fixed length 29 | //u32 fn_len; // file name length, not RomFsHeader part, only for convenience. 30 | }RomFsHeader; 31 | 32 | 33 | typedef struct RomfsSuperBlock_ 34 | { 35 | u8 id_str[8]; 36 | u32 size; 37 | u32 checksum; 38 | char volume_name[0]; 39 | }RomfsSuperBlock_; 40 | 41 | typedef struct RomfsINode_ 42 | { 43 | u32 nextfh; 44 | u32 spec; 45 | u32 size; 46 | u32 checksum; 47 | char fn_name[0]; 48 | }RomfsINode_; 49 | 50 | static inline u32 get_next_16_boundary(int cur_offset) 51 | { 52 | u32 len = cur_offset; 53 | 54 | if (len&15) 55 | { 56 | len += 16-(len&15); 57 | } 58 | //len+=16; // next 16 boundary 59 | return len; 60 | } 61 | 62 | static inline u8 get_file_type(u8 t) 63 | { 64 | return (t & 7); 65 | } 66 | 67 | char * k_readdir(const char *dirname); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /c-bootloader/cppb.cpp: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | /* 3 | * c bootloader 4 | */ 5 | 6 | //#define POINTER_TEST 7 | 8 | void print(const char *s, const char *msg="\r\ng++ test"); 9 | 10 | int bbb=0; // test bss section 11 | 12 | extern "C" void WinMain(void) 13 | { 14 | __asm__ ("mov %cs, %ax\n"); 15 | __asm__ ("mov %ax, %ds\n"); 16 | __asm__ ("mov %ax, %ss\n"); 17 | __asm__ ("mov $0xfff0, %sp\n"); 18 | #ifdef POINTER_TEST 19 | unsigned char *vb = (unsigned char *)0xb8000; 20 | *vb = 'A'; 21 | *(unsigned char *)0xb8001 = 0xc; 22 | *(unsigned char *)0xb8002 = 'B'; 23 | *(unsigned char *)0xb8003 = 0xc; 24 | #else 25 | print("hello cpp"); 26 | #if 0 27 | unsigned char *vb = (unsigned char *)0xb8000; 28 | *vb = 'A'; 29 | *(unsigned char *)0xb8001 = 0xc; 30 | *(unsigned char *)0xb8002 = 'B'; 31 | *(unsigned char *)0xb8003 = 0x9; 32 | *(unsigned char *)0xb8004 = '@'; 33 | *(unsigned char *)0xb8005 = 0xc; 34 | #endif 35 | #endif 36 | while(1); 37 | } 38 | 39 | #ifndef POINTER_TEST 40 | void print(const char *s, const char *msg) 41 | { 42 | #if 1 43 | while(*s) 44 | { 45 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 46 | s++; 47 | } 48 | #endif 49 | #if 1 50 | while(*msg) 51 | { 52 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *msg), "b"(7)); 53 | msg++; 54 | } 55 | #endif 56 | } 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /include/k_string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include "type.h" 5 | 6 | // kernel loader part function 7 | void asm_memcpy(u8 *dest, u8 *src, int n); 8 | void asm_seg_memcpy(u8 *dest, u8 *src, int n, u16 fs); 9 | void asm_absolute_memcpy(u8 *dest, u8 *src, int n); 10 | 11 | // prefix s is simple; 32 means in protoected mode 12 | static inline u32 s_strlen(const char *s) 13 | { 14 | u8 len=0; 15 | 16 | while(*s++) 17 | ++len; 18 | return len; 19 | } 20 | 21 | static inline char* s_strcpy(char *dest, const char *src) 22 | { 23 | char *p = dest; 24 | while(*src) 25 | *dest++ = *src++; 26 | *dest='\0'; 27 | return p; 28 | } 29 | 30 | static inline int s_strcmp(const char *s1, const char *s2) 31 | { 32 | s8 res; 33 | while(1) 34 | if ((res = *s1 - *s2++) != 0 || !*s1++) 35 | break; 36 | return res; 37 | } 38 | 39 | static inline int s_memcmp(const char *s1, const char *s2, int n) 40 | { 41 | if ((s1 == 0) || (s2 == 0)) 42 | { /* for robustness */ 43 | return (s1 - s2); 44 | } 45 | 46 | const char * p1 = (const char *)s1; 47 | const char * p2 = (const char *)s2; 48 | int i; 49 | for (i = 0; i < n; i++,p1++,p2++) 50 | { 51 | if (*p1 != *p2) 52 | { 53 | return (*p1 - *p2); 54 | } 55 | } 56 | return 0; 57 | } 58 | 59 | void p_asm_memcpy(void *dest, void *src, u32 n); 60 | void p_asm_memset(void *dest, int c, u32 n); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /storage.c: -------------------------------------------------------------------------------- 1 | #include "storage.h" 2 | #include "kl_global.h" 3 | #include "k_string.h" 4 | 5 | #define RAMDISK_SECTOR_SIZE 512 6 | #define RAMDISK_SECTOR_MASK (~(RAMDISK_SECTOR_SIZE-1)) 7 | #define RAMDISK_SECTOR_OFFSET ((RAMDISK_SECTOR_SIZE-1)) 8 | 9 | extern int __romfs_start__, __romfs_end__; 10 | 11 | int ramdisk_dout(StorageDevice *sd, void *dest, u32 addr, u32 size) 12 | { 13 | p_asm_memcpy((u8*)dest, (u8 *)(addr+sd->start_pos), size); 14 | //dump_u8((u8 *)(addr+sd->start_pos) , 16); 15 | //dump_u8((u8 *)(dest) , 16); 16 | //*(u8 *)(dest) = 0xff; 17 | 18 | return size; 19 | } 20 | 21 | #define RAMFS_ADDR (16*RAMDISK_ES + LOAD_KERNEL_OFFSET) 22 | 23 | 24 | 25 | // c99 26 | StorageDevice ramdisk_sd= 27 | { 28 | .dout = ramdisk_dout, 29 | .sector_size = RAMDISK_SECTOR_SIZE, 30 | .storage_size = 2*1024*1024, 31 | //.storage_size = (int)&__romfs_end__ - (int)&__romfs_start__, 32 | //.start_pos = 0x40800000, 33 | .start_pos = (int)&__romfs_start__, 34 | }; 35 | 36 | int ramdisk_driver_init(void) 37 | { 38 | int ret; 39 | ramdisk_sd.storage_size = (int)&__romfs_end__ - (int)&__romfs_start__; 40 | ret = register_storage_device(&ramdisk_sd, RAMDISK); 41 | return ret; 42 | } 43 | 44 | StorageDevice *storage[MAX_STORAGE_DEVICE]; 45 | 46 | int register_storage_device(StorageDevice *sd, u32 num) 47 | { 48 | if (storage[num]) 49 | return -1; 50 | else 51 | { 52 | storage[num] = sd; 53 | return 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /asm_syscall.S: -------------------------------------------------------------------------------- 1 | #include "asm_syscall.h" 2 | #include "process_const.h" 3 | 4 | .code32 5 | .extern save 6 | 7 | .text 8 | 9 | #ifndef IPC 10 | .global get_ticks 11 | get_ticks: 12 | mov $_NR_GET_TICKS, %eax 13 | int $INT_VECTOR_SYS_CALL 14 | ret 15 | #endif 16 | 17 | .global set_vga_mode 18 | set_vga_mode: 19 | mov $_NR_SET_VGA_MODE, %eax 20 | int $INT_VECTOR_SYS_CALL 21 | ret 22 | 23 | .global write 24 | write: 25 | mov $_NR_WRITE, %eax 26 | mov 4(%esp), %ebx 27 | mov 8(%esp), %ecx 28 | int $INT_VECTOR_SYS_CALL 29 | ret 30 | 31 | .global sendrec 32 | sendrec: 33 | push %ebx 34 | push %ecx 35 | push %edx 36 | # why not need push %eax 37 | 38 | mov $_NR_SENDREC, %eax 39 | mov 16(%esp), %ebx # 12+4 40 | mov 20(%esp), %ecx # 12+8 41 | mov 24(%esp), %edx # 12+12 42 | int $INT_VECTOR_SYS_CALL 43 | 44 | pop %edx 45 | pop %ecx 46 | pop %ebx 47 | 48 | ret 49 | 50 | .global app_print 51 | app_print: 52 | mov $_NR_APP_PRINT, %eax 53 | mov 4(%esp), %edx 54 | int $INT_VECTOR_SYS_CALL 55 | ret 56 | 57 | .global printk 58 | printk: 59 | mov $_NR_PRINTK, %eax 60 | mov 4(%esp), %edx 61 | int $INT_VECTOR_SYS_CALL 62 | ret 63 | 64 | .global sys_call 65 | sys_call: 66 | call save 67 | sti 68 | push %esi # why push %esi ?? 69 | 70 | pushl ready_process 71 | push %edx 72 | push %ecx 73 | push %ebx 74 | call *sys_call_table(, %eax, 4) 75 | add $16, %esp 76 | pop %esi # why pop %esi ?? 77 | mov %eax, P_EAX_OFFSET(%esi) # return value save to eax offset in process structure 78 | cli 79 | ret 80 | 81 | -------------------------------------------------------------------------------- /c-bootloader/cpp/global_object/cppb.cpp: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | #include "io.h" 3 | 4 | /* 5 | * c bootloader 6 | */ 7 | 8 | //#define POINTER_TEST 9 | 10 | 11 | #define BOCHS_MB __asm__ __volatile__("xchg %bx, %bx"); 12 | 13 | 14 | Io io; 15 | 16 | extern int _start_ctors; 17 | extern int _end_ctors; 18 | 19 | extern "C" void WinMain(void) 20 | { 21 | BOCHS_MB 22 | #if 1 23 | __asm__ ("mov %cs, %ax\n"); 24 | __asm__ ("mov %ax, %ds\n"); 25 | __asm__ ("mov %ax, %ss\n"); 26 | 27 | int ctor_addr_start = _start_ctors; 28 | int ctor_addr_end = _end_ctors; 29 | typedef void (*FuncPtr)(); 30 | FuncPtr fp = (FuncPtr)(ctor_addr_start); 31 | fp(); 32 | #if 0 33 | for (int i = ctor_addr_start; i < ctor_addr_end ; ++i) 34 | { 35 | } 36 | 37 | #endif 38 | //__asm__ ("mov $0xfff0, %sp\n"); 39 | { 40 | io.print("hello cpp class\r\n"); 41 | } 42 | #if 0 43 | unsigned char *vb = (unsigned char *)0xb8000; 44 | *vb = 'A'; 45 | *(unsigned char *)0xb8001 = 0xc; 46 | *(unsigned char *)0xb8002 = 'B'; 47 | *(unsigned char *)0xb8003 = 0x9; 48 | *(unsigned char *)0xb8004 = '@'; 49 | *(unsigned char *)0xb8005 = 0xc; 50 | #endif 51 | //while(1); 52 | __asm__ ("mov $0x4c00, %ax\n"); 53 | __asm__ ("int $0x21\n"); // 回到 DOS 54 | 55 | #endif 56 | } 57 | 58 | 59 | 60 | void *__dso_handle; 61 | extern "C" 62 | { 63 | int __cxa_atexit(void (*destructor) (void *), void *arg, void *__dso_handle) 64 | { 65 | io.print("hello cc\r\n"); 66 | return 0; 67 | } 68 | void __cxa_finalize(void *d) 69 | { 70 | io.print("hello dtor\r\n"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /b.c: -------------------------------------------------------------------------------- 1 | __asm__(".code16gcc\n"); 2 | 3 | typedef unsigned char u8; 4 | typedef unsigned int u32; 5 | 6 | int i; 7 | char* itoa(int n, char* str); 8 | 9 | void print(const char *s) 10 | { 11 | while(*s) 12 | { 13 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 14 | s++; 15 | } 16 | } 17 | 18 | int p() 19 | { 20 | int c=i+1; 21 | char arr[6]="a"; 22 | char *s = arr; 23 | 24 | //const char *str="test"; 25 | //volatile u8 *video_addr = (u8*)0xB8000; 26 | //asm("movw $0xb000 %gs"); 27 | //*video_addr = 'a'; 28 | s = itoa(c, s); 29 | print(s); 30 | return c; 31 | } 32 | 33 | #if 1 34 | char* itoa(int n, char* str) 35 | { 36 | char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 37 | char* p=str; 38 | char* head=str; 39 | int radix = 10; 40 | 41 | // if(!p || radix < 2 || radix > 36) 42 | // return p; 43 | if (n==0) 44 | { 45 | *p++='0'; 46 | *p=0; 47 | return str; 48 | } 49 | #if 1 50 | if (radix == 10 && n < 0) 51 | { 52 | *p++='-'; 53 | n= -n; 54 | } 55 | #endif 56 | while(n) 57 | { 58 | *p++=digit[n%radix]; 59 | n/=radix; 60 | } 61 | *p=0; 62 | #if 1 63 | for (--p; head < p ; ++head, --p) 64 | { 65 | char temp=*head; 66 | *head=*p; 67 | *p=temp; 68 | } 69 | #endif 70 | return str; 71 | } 72 | #endif 73 | 74 | #if 0 75 | extern u32 __bss_start__; 76 | extern u32 __bss_end__; 77 | void init_bss() 78 | { 79 | u8 *bss=(u8*)__bss_start__; 80 | *bss = 0x1; 81 | *(bss+1) = 0x1; 82 | *(bss+2) = 0x1; 83 | *(bss+3) = 0x1; 84 | #if 0 85 | while (i!=(u8*)__bss_end__) 86 | { 87 | *i = 0x1; 88 | ++i; 89 | } 90 | #endif 91 | } 92 | #endif 93 | -------------------------------------------------------------------------------- /systask.c: -------------------------------------------------------------------------------- 1 | /* 2 | * system task 3 | */ 4 | 5 | #include "process.h" 6 | #include "k_assert.h" 7 | #include "mm.h" 8 | 9 | void task_sys(void) 10 | { 11 | extern u32 ticks; 12 | 13 | Message msg; 14 | while(1) 15 | { 16 | #ifdef IPC 17 | send_recv(RECEIVE, ANY, &msg); 18 | int src = msg.source; 19 | switch (msg.type) 20 | { 21 | case GET_TICKS: 22 | { 23 | msg.RETVAL = ticks; 24 | send_recv(SEND, src, &msg); 25 | break; 26 | } 27 | default : 28 | { 29 | panic("unknown message type"); 30 | break; 31 | } 32 | } 33 | #endif 34 | } 35 | 36 | } 37 | 38 | Message mm_msg; 39 | 40 | void task_mm(void) 41 | { 42 | while(1) 43 | { 44 | send_recv(RECEIVE, ANY, &mm_msg); 45 | int src = mm_msg.source; 46 | int reply = 1; 47 | 48 | switch (mm_msg.type) 49 | { 50 | case FORK: 51 | { 52 | mm_msg.RETVAL = do_fork(); 53 | break; 54 | } 55 | case EXIT: 56 | { 57 | do_exit(mm_msg.STATUS); 58 | reply = 0; 59 | break; 60 | } 61 | case WAIT: 62 | { 63 | do_wait(); 64 | reply = 0; 65 | break; 66 | } 67 | case EXEC: 68 | { 69 | mm_msg.RETVAL = do_execl(); 70 | break; 71 | } 72 | default : 73 | { 74 | panic("unknown message type"); 75 | break; 76 | } 77 | } 78 | #if 1 79 | // evoke parent process 80 | if (reply) 81 | { 82 | mm_msg.type = SYSCALL_RET; 83 | send_recv(SEND, src, &mm_msg); 84 | int a = 5; // for debug setting break point 85 | } 86 | #endif 87 | } 88 | 89 | } 90 | 91 | -------------------------------------------------------------------------------- /include/k_stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef K_STDIO_H 2 | #define K_STDIO_H 3 | 4 | #include "type.h" 5 | #include "process.h" 6 | 7 | extern u8 *cur_vb; 8 | 9 | // char fg attribute 10 | #define HRED 0xc 11 | #define HGREEN 0xa 12 | #define HBLUE 0x9 13 | #define HWHITE 0xf 14 | 15 | #define RED 4 16 | #define GREEN 2 17 | #define BLUE 1 18 | #define WHITE 7 19 | 20 | #define EFLAGS_AC_BIT 0x00040000 21 | #define CR0_CACHE_DISABLE 0x60000000 22 | 23 | #define MAX_PATH 256 24 | 25 | // for kernel_loader.c 26 | // prefix s16 means Simple 16 bit code 27 | void s16_print_int(int i, int radix); 28 | void print(const char *s); 29 | 30 | // ========================= 31 | // for p_kernel.elf 32 | void s32_print_int(int i, u8 *vb, int radix); 33 | void s32_print(const u8 *s, u8 *vb); 34 | void clear_line(u8 line_no); 35 | void clear(); 36 | 37 | void p_dump_u8(u8 *buff, int len); 38 | void h2c(u8 hex, u8 ch[2]); 39 | void print_num(int n, u8 *sy); 40 | 41 | //bios int 16-0, Wait for Keypress and Read Character 42 | //so all previous bios print messages may be seen 43 | static inline void bios_wait_key() 44 | { 45 | __asm__ __volatile__("xor %eax,%eax\n"); 46 | __asm__ __volatile__("int $0x16\n"); 47 | } 48 | 49 | // reset disk 50 | static inline void bios_reset_disk() 51 | { 52 | __asm__ __volatile__("mov $0, %ah\n"); 53 | __asm__ __volatile__("mov 0x0, %dl\n"); 54 | __asm__ __volatile__("int $0x13\n"); 55 | } 56 | 57 | int s32_sprintf(char *str_buf, const char *format, ...); 58 | int s32_vsprintf(char *str_buf, const char *fmt, char * ap); 59 | int s32_printf(const char *fmt, ...); 60 | int sys_printk(int unused1, int unused2, char *s, struct Process_ *proc); 61 | int printx(const char *fmt, ...); 62 | void h2c(u8 hex, u8 ch[2]); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /io/k_stdio_k.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel io function 3 | */ 4 | 5 | #include "syscall.h" 6 | #include "console.h" 7 | #include "k_stdio.h" 8 | #include "k_stdlib.h" 9 | 10 | int s32_printf(const char *fmt, ...) 11 | { 12 | char buf[256]; 13 | int i=1; 14 | char *p = buf; 15 | 16 | for (; *fmt ; ++fmt) 17 | { 18 | if (*fmt != '%') 19 | { 20 | *p++ = *fmt; 21 | continue; 22 | } 23 | ++fmt; 24 | u8 *arg = (u8 *)(&fmt + i); // nst argument address 25 | u32 arg_content = *((u32*)arg); 26 | 27 | switch (*fmt) 28 | { 29 | case 'd': 30 | { 31 | u8 str[12]=""; 32 | s32_itoa(arg_content, str, 10); 33 | 34 | char *str_ptr = str; 35 | while(*str_ptr) 36 | *p++ = *str_ptr++; 37 | break; 38 | } 39 | case 'x': 40 | { 41 | u8 str[12]=""; 42 | s32_itoa(arg_content, str, 16); 43 | 44 | char *str_ptr = str; 45 | while(*str_ptr) 46 | *p++ = *str_ptr++; 47 | break; 48 | } 49 | case 's': 50 | { 51 | char *str_ptr = (char *)arg_content; 52 | while(*str_ptr) 53 | *p++ = *str_ptr++; 54 | break; 55 | } 56 | default: 57 | break; 58 | } 59 | ++i; // point to next argument 60 | 61 | } // end for (char *p = buf; *fmt ; ++fmt, ++i) 62 | int len = p-buf; 63 | //buf[len]='\0'; 64 | 65 | int write(char *buf, int len); 66 | write(buf, len); 67 | 68 | return 0; 69 | } 70 | 71 | int printx(const char *fmt, ...) 72 | { 73 | // int printk(char *s); 74 | 75 | int i; 76 | char buf[256]; 77 | char *arg = (char *)(&fmt+1); 78 | 79 | i = s32_vsprintf(buf, fmt, arg); 80 | printk(buf); // system call 81 | //while(1); 82 | return i; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /include/console.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSOLE_H 2 | #define CONSOLE_H 3 | 4 | #include "tty.h" 5 | #include "type.h" 6 | 7 | // char fg attribute 8 | #define HRED 0xc 9 | #define HGREEN 0xa 10 | #define HBLUE 0x9 11 | #define HWHITE 0xf 12 | 13 | #define RED 4 14 | #define GREEN 2 15 | #define BLUE 1 16 | #define WHITE 7 17 | 18 | // char bg attribute 19 | 20 | // video ram is from 0xb8000 ~ 0xc0000 21 | // need 4000 byte for 80X25 console 22 | 23 | #define TEXT_CONSOLE 0 24 | #define GRAPHIC_CONSOLE 1 25 | 26 | // 80X25 char 27 | #define CON_H 25 28 | #define CON_W 80 29 | 30 | typedef struct Console_ 31 | { 32 | u32 vm_start; // video memory start 33 | u32 vm_end; // video memroy end 34 | u32 cur_vm; 35 | u32 cur_x, cur_y; 36 | u8 type; // TEXT_CONSOLE means text console, GRAPHIC_CONSOLE means graphic console 37 | }Console; 38 | 39 | #define CONSOLE_NUM 4 40 | #define VIDEO_RAM_SIZE ((0xc0000-0xb8000) / (CONSOLE_NUM-1) ) // last console is graphic console 41 | 42 | extern Console console_table[]; 43 | 44 | void s32_print_char(u8 ch); 45 | void s32_print_str(const u8* str); 46 | 47 | void s32_set_text_color(u8 fg, u8 bg); 48 | 49 | int init_console(); 50 | void set_cursor(u16 pos); 51 | void set_video_start_addr(u16 addr); 52 | void s32_console_print_char(Console *console, u8 ch); 53 | void s32_console_print_str(Console *console, const u8 *str); 54 | void s32_console_print_char_xy(Console *console, u8 ch, int x, int y); 55 | void s32_console_print_str_xy(Console *console, const u8 *str, int x, int y); 56 | void set_xy(Console *console, int x, int y); 57 | void get_xy(Console *console, int *x, int *y); 58 | inline static void clear_console(Console *console) 59 | { 60 | for (int y=0 ; y < 50 ; ++y) 61 | for (int x=0 ; x < 80 ; ++x) 62 | s32_console_print_char_xy(console, ' ', x, y); 63 | set_xy(console, 0, 2); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /c_init.s: -------------------------------------------------------------------------------- 1 | .code16 2 | .extern __bss_start__ 3 | .extern __bss_end__ 4 | 5 | .text 6 | .global _start 7 | _start: 8 | mov %cs, %ax 9 | mov %ax, %ds 10 | mov %ax, %es 11 | 12 | # setup stack 13 | mov %ax, %ss 14 | mov $0xffff, %sp 15 | 16 | # call disp_str 17 | call init_bss_asm 18 | call p 19 | # call disp_str2 20 | jmp . 21 | #disp_str: 22 | # mov $BootMessage, %ax 23 | # mov %ax,%bp 24 | # mov $16,%cx 25 | # mov $0x1301,%ax 26 | # mov $0x00c,%bx 27 | # mov $0,%dl 28 | # int $0x10 29 | # ret 30 | #BootMessage:.ascii "Hello, c-env world!" 31 | #disp_str2: 32 | # mov $str2, %ax 33 | # mov %ax,%bp 34 | # mov $5,%cx 35 | # mov $0x1301,%ax 36 | # mov $0x00c,%bx 37 | # mov $0,%dl 38 | # int $0x10 39 | # ret 40 | #str2:.ascii "after" 41 | 42 | 43 | # init bss 44 | init_bss_asm: 45 | movw $__bss_end__, %di /* Destination */ 46 | movw $__bss_start__, %si /* Source */ 47 | movw $0x0, %ax 48 | movw %ax, %gs 49 | jmp 2f 50 | 1: 51 | movw %si, %ax 52 | movb $0x1, %gs:(%eax) 53 | add $1, %si 54 | 55 | 2: 56 | cmpw %di, %si 57 | jne 1b 58 | ret 59 | 60 | # movw 16(%ebp), %ecx /* Counter */ 61 | #1: 62 | # cmp $0, %ecx /* Loop counter */ 63 | # jz MemCpy.2 64 | # movb %ds:(%esi), %al 65 | # inc %esi 66 | # movb %al, %es:(%edi) 67 | # inc %edi 68 | # dec %ecx 69 | # jmp MemCpy.1 70 | #2: 71 | # mov 8(%ebp), %eax 72 | # pop %ecx 73 | # pop %edi 74 | # pop %esi 75 | # mov %ebp, %esp 76 | # pop %ebp 77 | # ret 78 | 79 | 80 | 81 | #.bss 82 | #_bss_start_:.word __bss_start__ 83 | #_bss_end_:.word __bss_end__ 84 | 85 | .data 86 | #LABEL_STACK: 87 | #.space 512, 0 88 | 89 | 90 | #.section ss 91 | # mov %ax, %es 92 | #.org 510 93 | #.word 0xaa55 94 | 95 | -------------------------------------------------------------------------------- /kernel_loader/makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -O0 2 | #CFLAGS = -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -I../include 3 | #ASFLAGS = --32 -g 4 | #LDFLAGS = -m elf_i386 5 | 6 | ifdef COMSPEC 7 | # in windows 8 | include ..\rule.mk 9 | else 10 | include ../rule.mk 11 | endif 12 | 13 | ifdef REAL_PC 14 | CFLAGS+=-DREAL_PC 15 | endif 16 | 17 | # enter protected mode kernel loader 18 | kloaderp.bin: kloaderp.bin.elf 19 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 20 | 21 | kloaderp.bin.elf: kloader_init.o kernel_loader.o protected_code.o ../io/k_stdio.o 22 | ld $(LDFLAGS) -nostdlib -g -o $@ -Tklp.ld $^ 23 | 24 | kloader_init.o: kloader_init.S 25 | $(CC) $(CFLAGS) -o $@ -c $< 26 | 27 | #protected_code.o: protected_code.c 28 | # gcc $(CFLAGS) -c $< 29 | protected_code.s: protected_code.c 30 | $(CC) $(CFLAGS) -o $@ -S $< 31 | #kernel_loader.o: kernel_loader.c elf.h 32 | # gcc -std=c99 $(CFLAGS) -c $< 33 | #kernel_loader.o: kernel_loader.s 34 | # as $(ASFLAGS) -o $@ $< 35 | #kernel_loader.s: kernel_loader.c elf.h 36 | #kernel_loader.s: kernel_loader.c ../include/type.h ../include/elf.h ../include/k_string.h ../include/type.h 37 | # gcc $(CFLAGS) -o $@ -S $< 38 | protected_code.e: protected_code.c 39 | gcc $(CFLAGS) -E -o $@ -S $< 40 | #kernel_loader.e: kernel_loader.c 41 | # gcc $(CFLAGS) -E -o $@ -S $< 42 | 43 | ../io/k_stdio.o: ../io/k_stdio.c 44 | (cd ../io; make) 45 | 46 | 47 | 48 | .PHONE: clean 49 | 50 | clean: 51 | rm -rf *.o *.elf *.bin kernel_loader.s *.d *.e 52 | 53 | sources = kernel_loader.c protected_code.c 54 | include $(sources:.c=.d) 55 | 56 | 57 | # ref: http://www.gnu.org/software/make/manual/make.html 58 | #%.d: %.c 59 | #@set -e; rm -f $@; \ 60 | #$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ 61 | #sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ 62 | #rm -f $@.$$$$ 63 | 64 | kernel_loader: kernel_loader.c 65 | gcc -DIPC -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -Iinclude -I../include -DDOS_PROG -o kernel_loader kernel_loader.c 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | simple os: 2 | on the x86/32 bit mode platform. 3 | * using x86 protected mode. 4 | * process switch. 5 | * implement fork/exec/wait. 6 | * support vga graphic mode, in protected mode switch to graphic mode and switch back to text mode. 7 | * kernel loader can load more than 1M size kernel (using Unreal mode). 8 | * ipc. 9 | * ramdisk. 10 | 11 | demo video: 12 | 13 | [![IMAGE ALT TEXT](https://img.youtube.com/vi/wtTc2bLOnFY/0.jpg)](https://www.youtube.com/watch?v=wtTc2bLOnFY) 14 | 15 | boot loader loads the kernel loader (kernel_loader/kloaderp.bin) to 0x9000:0x0100. 16 | 17 | in kernel loader, init c runtime, then use c code (16 bit) read elf kerenl 18 | (in Unreal mode) to memory address 0x300000+0x28*16 (by bios 0x13), 19 | then enter protected mode. 20 | 21 | in protected mode, copy the the p_kernel.elf (c code, in the state, only can use stack variable) 22 | follow the elf header information (Program Headers:). 23 | then jump to the kernel address (elf entry point address). 24 | 25 | kloaderp.bin load p_kernel.elf to 0x300000+0x28*16 26 | 27 | than copy p_kernel.elf by elf information to absolute address 0x100000. 28 | kernel load address depends k.ld (. = 0x100000), current is 0x100000. 29 | p_kernel.elf entry pointer is 0x100000. 30 | 31 | ramdisk filesystem is romfs. 32 | it is megered to p_kernel.elf. 33 | 34 | tty design: 35 | 0, 1, 2 text mode alt+f1, alt+f2, alt+f3 36 | The 3rd tty is graphic mode (alt+f6) 37 | now can switch graphic/text mode tty. 38 | 39 | the url show some pictures and a vidoe demo (in real pc). 40 | (http://descent-incoming.blogspot.tw/2013/02/x86-1m-kernel.html) 41 | 42 | make test floppy image 43 | boot.bin is boot loader 44 | c-bootloader/mkimg.sh -b boot.bin -d boot.img 45 | 46 | copy kernel loader and kernel to floppy image 47 | ./script/cp2img.sh 48 | 49 | modify REAL_PC macro 50 | kernel_loader/protected_code.c 51 | if only in emulator, comment #define REAL_PC 52 | 53 | compile/test: 54 | qemu: 55 | make 56 | 57 | real pc: 58 | make REAL_PC=1 59 | 60 | qemu cmd: 61 | qemu-system-i386 -fda boot.img --nographic # ctrl+a x to exit 62 | qemu-system-i386 -fda boot.img --display sdl 63 | qemu-system-i386 -fda boot.img --display curses # esc + 1, esc + 2 q enter to exit ref: http://stackoverflow.com/questions/14165158/how-to-switch-to-qemu-monitor-console-when-running-with-curses 64 | qemu-system-i386 -fda boot.img 65 | 66 | bochs cmd: 67 | bochs 1.6.8 configure file 68 | x86.bxrc for bochs debugger 69 | x86-gdb.bxrc for gdb 70 | bochs -f x86.bxrc 71 | 72 | -------------------------------------------------------------------------------- /include/protect.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTECT_H 2 | #define PROTECT_H 3 | #include "type.h" 4 | 5 | #define GDT_SIZE 128 6 | #define IDT_SIZE 256 7 | 8 | #define INDEX_TSS 4 9 | #define INDEX_LDT_FIRST 5 10 | 11 | 12 | // 8 byte 13 | typedef struct Descriptor_ 14 | { 15 | u16 limit_low; 16 | u16 base_low; 17 | u8 base_mid; 18 | u8 attr1; 19 | u8 limit_high_attr2; 20 | u8 base_high; 21 | }Descriptor; 22 | 23 | // 8 byte 24 | typedef struct Gate_ 25 | { 26 | u16 offset_low; 27 | u16 selector; 28 | u8 dcount; 29 | u8 attr; 30 | u16 offset_high; 31 | }Gate; 32 | 33 | #define SELECTOR_KERNEL_CS 8 34 | #define SELECTOR_KERNEL_DS 16 // (8*2) 35 | #define SELECTOR_KERNEL_GS 24+3 // (8*3) , RPL: 3 36 | 37 | // ldt index 38 | #define LDT_CODE 0 39 | #define LDT_DATA 1 40 | 41 | #define SELECTOR_TSS 8*4 42 | 43 | #define DA_386IGate 0x8E /* 386 中斷門類型值 */ 44 | #define DA_C 0x98 45 | #define DA_DRW 0x92 46 | #define DA_386TSS 0x89 // 可用 386 任務狀態段類型值 47 | #define DA_LDT 0x82 // 局部描述符表段類型值 48 | #define DA_32 0x4000 /* 32 位段 */ 49 | #define DA_DR 0x90 /* 存在的只讀數據段類型值 */ 50 | #define DA_DRW 0x92 /* 存在的可讀寫數據段屬性值 */ 51 | #define DA_DRWA 0x93 /* 存在的已訪問可讀寫數據段類型值 */ 52 | #define DA_C 0x98 // 存在的只執行代碼段屬性值 53 | #define DA_LIMIT_4K 0x8000 // 段界限粒度為 4K 字節 54 | 55 | #define LIMIT_4K_SHIFT 12 56 | #define PROC_IMAGE_SIZE_DEFAULT 0x100000 /* 1 MB */ 57 | 58 | 59 | 60 | 61 | #define PRIVILEGE_KRNL 0 62 | #define PRIVILEGE_USER 3 63 | 64 | #define SEL_USE_LDT 4 65 | #define SEL_USE_GDT 0 66 | 67 | static inline void init_descriptor(Descriptor *desc, u32 base, u32 limit, u16 attr) 68 | { 69 | desc->limit_low = (limit & 0xffff); 70 | desc->base_low = (base & 0xffff); 71 | desc->base_mid = ( (base >> 16) & 0xff); 72 | desc->attr1 = (attr & 0xff); 73 | desc->limit_high_attr2 = ((limit << 16) & 0x0f)| (attr >> 8) & 0xf0; 74 | desc->base_high = ((base >> 24) & 0xff); 75 | } 76 | 77 | static inline u32 seg2base(u16 seg) 78 | { 79 | extern Descriptor gdt[]; 80 | 81 | Descriptor *desc = &gdt[seg >> 3]; 82 | return ( (desc->base_high << 24) | (desc->base_mid << 16) | desc->base_low ); 83 | } 84 | 85 | static inline u32 linear2phy(u32 base, u32 offset) 86 | { 87 | return (base+offset); 88 | } 89 | 90 | #define reassembly(high, high_shift, mid, mid_shift, low) \ 91 | (((high) << (high_shift)) + \ 92 | ((mid) << (mid_shift)) + \ 93 | (low)) 94 | 95 | 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /b_by_bootloader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * let bootloader load to memory 3 | */ 4 | asm(".code16gcc\n"); 5 | 6 | typedef unsigned char u8; 7 | typedef unsigned int u32; 8 | 9 | int i; 10 | char* itoa(int n, char* str); 11 | 12 | void print(const char *s) 13 | { 14 | while(*s) 15 | { 16 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 17 | s++; 18 | } 19 | } 20 | 21 | #define DATA 22 | 23 | const int A = 10; 24 | #ifdef DATA 25 | char data_str[]="data_string"; 26 | #endif 27 | 28 | void write_mem8(u32 addr, u8 data); // assembly function. 29 | 30 | int p() 31 | { 32 | write_mem8(0x4, 'Z'); // assembly function. 33 | #if 0 34 | int c=i+1; 35 | char arr[10]="a"; 36 | char *s = arr; 37 | #endif 38 | #if 0 39 | char stack_str[]="stack_string"; // need %ds = %ss 40 | print("\r\n"); 41 | print(stack_str); 42 | #endif 43 | #if 0 44 | const char *ro_str="ro_string"; // movl $0x000002f0, %ss:-4(%ebp) 45 | print("\r\n"); 46 | print(ro_str); 47 | #endif 48 | 49 | #ifdef DATA 50 | print("\r\n"); 51 | print(data_str); 52 | #endif 53 | 54 | #if 0 55 | static char *s_str="static_point"; 56 | static char s_str_a[]="static_array"; 57 | print("\r\n"); 58 | print(s_str); 59 | print("\r\n"); 60 | print(s_str_a); 61 | #endif 62 | 63 | //const char *str="test"; 64 | //volatile u8 *video_addr = (u8*)0xB8000; 65 | //asm("movw $0xb000 %gs"); 66 | //*video_addr = 'a'; 67 | #if 0 68 | s = itoa(c, s); // need %ds to 0 69 | print("\r\n"); 70 | print(s); 71 | return c; 72 | #else 73 | return 1; 74 | #endif 75 | } 76 | 77 | #if 1 78 | char* itoa(int n, char* str) 79 | { 80 | char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 81 | char* p=str; 82 | char* head=str; 83 | int radix = 10; 84 | 85 | // if(!p || radix < 2 || radix > 36) 86 | // return p; 87 | if (n==0) 88 | { 89 | *p++='0'; 90 | *p=0; 91 | return str; 92 | } 93 | #if 0 94 | if (radix == 10 && n < 0) 95 | { 96 | *p++='-'; 97 | n= -n; 98 | } 99 | #endif 100 | while(n) 101 | { 102 | *p++=digit[n%radix]; 103 | n/=radix; 104 | } 105 | *p=0; 106 | #if 1 107 | for (--p; head < p ; ++head, --p) 108 | { 109 | char temp=*head; 110 | *head=*p; 111 | *p=temp; 112 | } 113 | #endif 114 | return str; 115 | } 116 | #endif 117 | 118 | #if 0 119 | extern u32 __bss_start__; 120 | extern u32 __bss_end__; 121 | void init_bss() 122 | { 123 | u8 *bss=(u8*)__bss_start__; 124 | *bss = 0x1; 125 | *(bss+1) = 0x1; 126 | *(bss+2) = 0x1; 127 | *(bss+3) = 0x1; 128 | #if 0 129 | while (i!=(u8*)__bss_end__) 130 | { 131 | *i = 0x1; 132 | ++i; 133 | } 134 | #endif 135 | } 136 | #endif 137 | -------------------------------------------------------------------------------- /c-bootloader/bhp.S: -------------------------------------------------------------------------------- 1 | # enter protect mode 2 | 3 | .code16 4 | .text 5 | .global begin 6 | jmp begin 7 | 8 | /* Segment Descriptor data structure. 9 | Usage: Descriptor Base, Limit, Attr 10 | Base: 4byte 11 | Limit: 4byte (low 20 bits available) 12 | Attr: 2byte (lower 4 bits of higher byte are always 0) */ 13 | .macro Descriptor Base, Limit, Attr 14 | .2byte \Limit & 0xFFFF 15 | .2byte \Base & 0xFFFF 16 | .byte (\Base >> 16) & 0xFF 17 | .2byte ((\Limit >> 8) & 0xF00) | (\Attr & 0xF0FF) 18 | .byte (\Base >> 24) & 0xFF 19 | .endm 20 | 21 | .set DA_32, 0x4000 /* 32-bit segment */ 22 | .set DA_LIMIT_4K, 0x8000 /* 4K */ 23 | .set DA_CR, 0x9A /* Execute/Read */ 24 | .set DA_DRW, 0x92 /* Read/Write */ 25 | 26 | gdt0: Descriptor 0, 0, 0 27 | gdt1: Descriptor 0, 0xfffff, DA_CR | DA_32 | DA_LIMIT_4K 28 | gdt2: Descriptor 0, 0xfffff, DA_DRW | DA_32 | DA_LIMIT_4K 29 | .set gdt_len, (. - gdt0) 30 | gdt_ptr: .2byte (gdt_len -1 ) # limit 31 | .4byte 0 # base 32 | 33 | .set selector_code, (gdt1-gdt0) 34 | .set selector_data, (gdt2-gdt0) 35 | 36 | 37 | 38 | begin: 39 | mov %cs,%ax 40 | mov %ax,%ds 41 | mov %ax,%es 42 | mov %ax,%ss 43 | 44 | # mov $0xb8000, %edi 45 | # movb $'R', (%edi) 46 | # mov $0xb8001, %edi 47 | # movb $0xc, (%edi) 48 | # jmp . 49 | 50 | xor %eax, %eax 51 | mov %cs, %ax 52 | shl $4, %eax 53 | add $gdt0, %eax /* eax <- gdt base*/ 54 | movl %eax, (gdt_ptr + 2) 55 | 56 | lgdt gdt_ptr 57 | 58 | cli 59 | # open a20 line 60 | inb $0x92, %al 61 | orb $0b00000010, %al 62 | outb %al, $0x92 63 | 64 | # enable protect mode 65 | movl %cr0, %eax 66 | orl $1, %eax 67 | movl %eax, %cr0 68 | 69 | ljmpl $selector_code, $seg_code32 70 | # ljmpl $selector_code, $0 71 | 72 | 73 | movw $0xb800, %ax 74 | movw %ax, %gs 75 | 76 | mov $0, %edi /* Destination */ 77 | mov $msg, %esi /* Source */ 78 | 79 | 1: 80 | #cmp $0, %ecx 81 | cmpb $0, (%esi) 82 | jz 2f 83 | movb %ds:(%esi), %al 84 | inc %esi 85 | movb %al, %gs:(%edi) 86 | inc %edi 87 | movb $0xc, %gs:(%edi) 88 | inc %edi 89 | dec %ecx 90 | jmp 1b 91 | 2: 92 | movb $'E', %gs:(160) 93 | jmp . 94 | #msg:.ascii "Hello GAS" 95 | msg: 96 | .asciz "Hello GAS" 97 | #.asciz "Hello World" 98 | .code32 99 | seg_code32: 100 | mov $selector_data, %ax 101 | mov %ax, %ds 102 | mov %ax, %es 103 | mov %ax, %ss 104 | mov $0xb8002, %edi /* Destination */ 105 | movb $'P', (%edi) 106 | mov $0xb8003, %edi /* Destination */ 107 | movb $0xc, (%edi) 108 | jmp . 109 | 110 | .org 510 111 | .word 0xaa55 112 | -------------------------------------------------------------------------------- /c-bootloader/pc/bhp.S: -------------------------------------------------------------------------------- 1 | # bootloader enter protect mode, then call c func 2 | 3 | .code16 4 | .text 5 | .global begin 6 | jmp begin 7 | 8 | /* Segment Descriptor data structure. 9 | Usage: Descriptor Base, Limit, Attr 10 | Base: 4byte 11 | Limit: 4byte (low 20 bits available) 12 | Attr: 2byte (lower 4 bits of higher byte are always 0) */ 13 | .macro Descriptor Base, Limit, Attr 14 | .2byte \Limit & 0xFFFF 15 | .2byte \Base & 0xFFFF 16 | .byte (\Base >> 16) & 0xFF 17 | .2byte ((\Limit >> 8) & 0xF00) | (\Attr & 0xF0FF) 18 | .byte (\Base >> 24) & 0xFF 19 | .endm 20 | 21 | .set DA_32, 0x4000 /* 32-bit segment */ 22 | .set DA_LIMIT_4K, 0x8000 /* 4K */ 23 | .set DA_CR, 0x9A /* Execute/Read */ 24 | .set DA_DRW, 0x92 /* Read/Write */ 25 | 26 | gdt0: Descriptor 0, 0, 0 27 | gdt1: Descriptor 0, 0xfffff, DA_CR | DA_32 | DA_LIMIT_4K 28 | gdt2: Descriptor 0, 0xfffff, DA_DRW | DA_32 | DA_LIMIT_4K 29 | .set gdt_len, (. - gdt0) 30 | gdt_ptr: .2byte (gdt_len -1 ) # limit 31 | .4byte 0 # base 32 | 33 | .set selector_code, (gdt1-gdt0) 34 | .set selector_data, (gdt2-gdt0) 35 | 36 | 37 | 38 | begin: 39 | xchg %bx, %bx 40 | mov %cs,%ax 41 | mov %ax,%ds 42 | mov %ax,%es 43 | mov %ax,%ss 44 | 45 | # mov $0xb8000, %edi 46 | # movb $'R', (%edi) 47 | # mov $0xb8001, %edi 48 | # movb $0xc, (%edi) 49 | # jmp . 50 | 51 | xor %eax, %eax 52 | mov %cs, %ax 53 | shl $4, %eax 54 | add $gdt0, %eax /* eax <- gdt base*/ 55 | movl %eax, (gdt_ptr + 2) 56 | 57 | lgdt gdt_ptr 58 | 59 | cli 60 | # open a20 line 61 | inb $0x92, %al 62 | orb $0b00000010, %al 63 | outb %al, $0x92 64 | 65 | # enable protect mode 66 | movl %cr0, %eax 67 | orl $1, %eax 68 | movl %eax, %cr0 69 | 70 | ljmpl $selector_code, $seg_code32 71 | # ljmpl $selector_code, $0 72 | 73 | 74 | movw $0xb800, %ax 75 | movw %ax, %gs 76 | 77 | mov $0, %edi /* Destination */ 78 | mov $msg, %esi /* Source */ 79 | 80 | 1: 81 | #cmp $0, %ecx 82 | cmpb $0, (%esi) 83 | jz 2f 84 | movb %ds:(%esi), %al 85 | inc %esi 86 | movb %al, %gs:(%edi) 87 | inc %edi 88 | movb $0xc, %gs:(%edi) 89 | inc %edi 90 | dec %ecx 91 | jmp 1b 92 | 2: 93 | movb $'E', %gs:(160) 94 | jmp . 95 | #msg:.ascii "Hello GAS" 96 | msg: 97 | .asciz "Hello GAS" 98 | #.asciz "Hello World" 99 | .code32 100 | seg_code32: 101 | mov $selector_data, %ax 102 | mov %ax, %ds 103 | mov %ax, %es 104 | mov %ax, %ss 105 | mov $0xb8004, %edi /* Destination */ 106 | movb $'P', (%edi) 107 | mov $0xb8005, %edi /* Destination */ 108 | movb $0x9, (%edi) 109 | call main 110 | 111 | #.org 510 112 | #.word 0xaa55 113 | -------------------------------------------------------------------------------- /c-bootloader/makefile: -------------------------------------------------------------------------------- 1 | #gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o vbr.o vbr.c 2 | #ld -static -Tlinker.ld -nostdlib --nmagic -o vbr.elf vbr.o 3 | #objcopy -O binary vbr.elf vbr.bin 4 | CFLAGS = -fno-stack-protector -std=c99 -Os -march=i686 -ffreestanding -Wall 5 | #CB_CFLAGS = -fno-stack-protector -std=c99 -march=i686 -ffreestanding -Wall 6 | CB_CFLAGS = -fno-stack-protector -std=c99 -m32 -ffreestanding -Wall -g 7 | CB_LDFLAGS = -m elf_i386 8 | 9 | CPPFLAGS = -m32 -g -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector 10 | 11 | 12 | all: bh.asm.bin bh.s.bin cb.bin bhp.bin vbr.bin 13 | 14 | vbr.bin: vbr.elf 15 | objcopy -O binary $< $@ 16 | 17 | vbr.elf: vbr.o 18 | ld -m elf_i386 -static -Tlinker.ld -nostdlib --nmagic -o $@ $< 19 | 20 | vbr.o: vbr.c code16gcc.h 21 | #gcc -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -c $< 22 | #gcc -Os -march=i686 -ffreestanding -Wall -Werror -I. -c $< 23 | gcc -Os $(CB_CFLAGS) -I. -c $< 24 | 25 | vbr-lba.bin: vbr-lba.elf 26 | objcopy -O binary $< $@ 27 | 28 | vbr-lba.elf: vbr-lba.o 29 | ld -static -Tlinker.ld -nostdlib --nmagic -o $@ $< 30 | 31 | vbr-lba.o: vbr-lba.c code16gcc.h 32 | #gcc -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -c $< 33 | gcc -Os -march=i686 -ffreestanding -Wall -Werror -I. -c $< 34 | 35 | #fat: fat.o 36 | # gcc -std=c99 -Os -march=i686 -ffreestanding -Wall -Werror -I. -o $@ $< 37 | #gcc -std=c99 -o $@ $< 38 | 39 | fat.bin: fat.bin.elf 40 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 41 | fat.bin.elf: fat.bin.o 42 | $(LD) -o $@ -Tlinker.ld $^ 43 | fat.com: fat.com.elf 44 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 45 | fat.com.elf: fat.com.o 46 | $(LD) -o $@ -Tlinker_dos.ld $^ 47 | fat.bin.o: fat.c 48 | gcc $(CFLAGS) -I. -o $@ -c $< 49 | fat.com.o: fat.c 50 | #gcc $(CFLAGS) -I. -o $@ -c $< 51 | gcc -DDOS_COM $(CFLAGS) -I. -o $@ -c $< 52 | #gcc -std=c99 -Os -march=i686 -ffreestanding -Wall -Werror -I. -c $< 53 | #gcc -std=c99 -c $< 54 | fat.s: fat.c 55 | gcc $(CFLAGS) -I. -S $< 56 | 57 | cb.s: cb.c 58 | gcc $(CB_CFLAGS) -I. -S $< 59 | cb.o: cb.c 60 | gcc $(CB_CFLAGS) -c $< 61 | cb.elf: cb.o l.ld 62 | ld $(CB_LDFLAGS) -static -Tl.ld -nostdlib -M -o cb.elf cb.o > cb.elf.map 63 | cb.bin: cb.elf 64 | objcopy -R .pdr -R .comment -R.note -S -O binary cb.elf cb.bin 65 | 66 | bh.s.o: bh.s 67 | as -o $@ $< 68 | bh.s.elf: bh.s.o 69 | ld -Tas.ld -o $@ $< 70 | 71 | bh.s.bin: bh.s.elf 72 | objcopy -O binary $< $@ 73 | 74 | bh.asm.bin: bh.asm 75 | nasm bh.asm -o bh.asm.bin 76 | bhp.o: bhp.S 77 | gcc -c bhp.S 78 | bhp.elf: bhp.o 79 | ld -Tas.ld -o bhp.elf bhp.o 80 | bhp.bin: bhp.elf 81 | objcopy -O binary $< $@ 82 | 83 | cppb.bin: cppb.elf 84 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 85 | cppb.elf: cppb.o l.ld 86 | ld $(CB_LDFLAGS) -static -Tl.ld -nostdlib -M -o $@ $< > cb.elf.map 87 | cppb.o: cppb.cpp 88 | g++ $(CPPFLAGS) -c $< 89 | 90 | 91 | clean: 92 | rm -rf *.o 93 | -------------------------------------------------------------------------------- /include/pm.h: -------------------------------------------------------------------------------- 1 | /* chapter3/1/pm.h 2 | 3 | Author: Wenbo Yang 4 | 5 | This file is part of the source code of book "Write Your Own OS with Free 6 | and Open Source Software". Homepage @ . 7 | 8 | This file is licensed under the GNU General Public License; either 9 | version 3 of the License, or (at your option) any later version. */ 10 | 11 | /* Comments below accords to "Chapter 3.4.5: Segment Descriptors" of "Intel 12 | 64 and IA-32 Arch. SW Developer's Manual: Volume 3A: System Programming 13 | Guide". */ 14 | 15 | /* GDT Descriptor Attributes 16 | DA_ : Descriptor Attribute 17 | D : Data Segment 18 | C : Code Segment 19 | S : System Segment 20 | R : Read-only 21 | RW : Read/Write 22 | A : Access */ 23 | .set DA_32, 0x4000 /* 32-bit segment */ 24 | .set DA_LIMIT_4K, 0x8000 /* 4K */ 25 | 26 | /* Descriptor privilege level */ 27 | .set DA_DPL0, 0x00 /* DPL = 0 */ 28 | .set DA_DPL1, 0x20 /* DPL = 1 */ 29 | .set DA_DPL2, 0x40 /* DPL = 2 */ 30 | .set DA_DPL3, 0x60 /* DPL = 3 */ 31 | 32 | /* GDT Code- and Data-Segment Types */ 33 | .set DA_DR, 0x90 /* Read-Only */ 34 | .set DA_DRW, 0x92 /* Read/Write */ 35 | .set DA_DRWA, 0x93 /* Read/Write, accessed */ 36 | .set DA_C, 0x98 /* Execute-Only */ 37 | .set DA_CR, 0x9A /* Execute/Read */ 38 | .set DA_CCO, 0x9C /* Execute-Only, conforming */ 39 | .set DA_CCOR, 0x9E /* Execute/Read-Only, conforming */ 40 | 41 | /* GDT System-Segment and Gate-Descriptor Types */ 42 | .set DA_LDT, 0x82 /* LDT */ 43 | .set DA_TaskGate, 0x85 /* Task Gate */ 44 | .set DA_386TSS, 0x89 /* 32-bit TSS(Available) */ 45 | .set DA_386CGate, 0x8C /* 32-bit Call Gate */ 46 | .set DA_386IGate, 0x8E /* 32-bit Interrupt Gate */ 47 | .set DA_386TGate, 0x8F /* 32-bit Trap Gate */ 48 | 49 | /* Selector Attributes */ 50 | .set SA_RPL0, 0 51 | .set SA_RPL1, 1 52 | .set SA_RPL2, 2 53 | .set SA_RPL3, 3 54 | .set SA_TIG, 0 55 | .set SA_TIL, 4 56 | 57 | /* Page Attributes */ 58 | .set PG_P, 1 59 | .set PG_RWR, 0 60 | .set PG_RWW, 2 61 | .set PG_USS, 0 62 | .set PG_USU, 4 63 | 64 | /* MACROS */ 65 | 66 | /* Segment Descriptor data structure. 67 | Usage: Descriptor Base, Limit, Attr 68 | Base: 4byte 69 | Limit: 4byte (low 20 bits available) 70 | Attr: 2byte (lower 4 bits of higher byte are always 0) */ 71 | .macro Descriptor Base, Limit, Attr 72 | .2byte \Limit & 0xFFFF 73 | .2byte \Base & 0xFFFF 74 | .byte (\Base >> 16) & 0xFF 75 | .2byte ((\Limit >> 8) & 0xF00) | (\Attr & 0xF0FF) 76 | .byte (\Base >> 24) & 0xFF 77 | .endm 78 | 79 | /* Gate Descriptor data structure. 80 | Usage: Gate Selector, Offset, PCount, Attr 81 | Selector: 2byte 82 | Offset: 4byte 83 | PCount: byte 84 | Attr: byte */ 85 | .macro Gate Selector, Offset, PCount, Attr 86 | .2byte (\Offset & 0xFFFF) 87 | .2byte \Selector 88 | .2byte (\PCount & 0x1F) | ((\Attr << 8) & 0xFF00) 89 | .2byte ((\Offset >> 16) & 0xFFFF) 90 | .endm 91 | -------------------------------------------------------------------------------- /kernel_loader/protected_code.c: -------------------------------------------------------------------------------- 1 | // test protected mode 2 | #include "type.h" 3 | #include "kl_global.h" 4 | #include "elf.h" 5 | #include "k_stdio.h" 6 | #include "k_stdlib.h" 7 | #include "k_string.h" 8 | 9 | int AA; 10 | 11 | void test_p(void) 12 | { 13 | u8 *vb = (u8 *)0xb8002; 14 | u8 *attr = (u8 *)0xb8003; 15 | 16 | *vb = 'M'; 17 | *attr = 9; 18 | #if 0 19 | while(1); 20 | #else 21 | __asm__ ("nop\t\n"); 22 | __asm__ ("nop\t\n"); 23 | #endif 24 | void jump_kernel(); 25 | jump_kernel(); 26 | } 27 | 28 | void jump_kernel() 29 | { 30 | __asm__ ("jmp $0x8, $0x5000\t\n"); 31 | __asm__ ("jmp 0x5000\t\n"); 32 | } 33 | 34 | void s32_memcpy(u8 *dest, const u8 *src, u32 n) 35 | { 36 | for (int i=0; i < n ; ++i) 37 | *dest++ = *src++; 38 | } 39 | 40 | //#define REAL_PC 41 | // in this state, cannot use global, static, bss data, 42 | // because this address is base on 0x100, but kloaderp.bin is loaded to 0x9000:0x0100, 43 | // so need added 0x9000X16 is global, static, bss data real address. 44 | // I only use stack for variable. 45 | // copy_elf_code() is run under protocted mode. 46 | void copy_elf_code(void) 47 | { 48 | void p_dump_memory(u32 dest, u32 src, int n); 49 | 50 | //p_dump_memory(1,2,3); 51 | 52 | u8 *vb = (u8 *)0xb8002; 53 | u8 *attr = (u8 *)0xb8003; 54 | 55 | *((u8 *)0xb8000) = 'P'; 56 | *vb = 'M'; 57 | *attr = 9; 58 | // copy kernel to proper position by elf information 59 | 60 | 61 | int line=10; 62 | //u8 *buff = (KERNEL_ES*16)+(u8*)LOAD_KERNEL_OFFSET; 63 | #ifdef REAL_PC 64 | u32 buff = LOAD_KERNEL_ADDR + (0x28*16); 65 | #else 66 | u32 buff = LOAD_KERNEL_ADDR; 67 | #endif 68 | //p_dump_u8(buff, 32); 69 | Elf32Ehdr *elf_header = (Elf32Ehdr*)buff; 70 | Elf32Phdr *elf_pheader = (Elf32Phdr*)((u8 *)buff + elf_header->e_phoff); 71 | // the load elf address maybe overlay entry ~ elf code size, so save entry first 72 | u32 entry = elf_header->e_entry; 73 | 74 | ++line; 75 | clear_line(line); 76 | s32_print_int(elf_header->e_entry, (u8*)(0xb8000+160*line), 16); 77 | 78 | 79 | //while(1); 80 | #if 0 81 | print("\r\nelf_header->e_entry: "); 82 | s16_print_int(elf_header->e_entry, 10); 83 | 84 | print("\r\nelf_header->e_phnum: "); 85 | s16_print_int(elf_header->e_phnum, 10); 86 | #endif 87 | 88 | //BOCHS_MB 89 | for (int i=0 ; i < elf_header->e_phnum; ++i) 90 | { 91 | ++line; 92 | clear_line(line); 93 | s32_print_int(elf_header->e_entry, (u8*)(0xb8000+160*line), 16); 94 | if (CHECK_PT_TYPE_LOAD(elf_pheader)) 95 | { 96 | //print_num(elf_pheader->p_vaddr, "elf_pheader->p_vaddr"); 97 | ++line; 98 | clear_line(line); 99 | s32_print_int(elf_pheader->p_vaddr, (u8*)(0xb8000+160*line), 16); 100 | 101 | ++line; 102 | clear_line(line); 103 | s32_print_int(elf_pheader->p_offset, (u8*)(0xb8000+160*line), 16); 104 | //print_num(elf_pheader->p_offset, "elf_pheader->p_offset"); 105 | //print_num(elf_pheader->p_filesz, "elf_pheader->p_filesz"); 106 | //asm_absolute_memcpy((u8*)elf_pheader->p_vaddr, buff+(elf_pheader->p_offset), elf_pheader->p_filesz); 107 | 108 | 109 | s32_memcpy((u8*)elf_pheader->p_vaddr, buff+(elf_pheader->p_offset), elf_pheader->p_filesz); 110 | //BOCHS_MB 111 | } 112 | ++elf_pheader; 113 | } 114 | //BOCHS_MB 115 | ++line; 116 | clear_line(line); 117 | s32_print_int(elf_header->e_entry, (u8*)(0xb8000+160*line), 16); 118 | //buff = LOAD_KERNEL_ADDR + (0x28*16); 119 | //p_dump_u8(buff, 48); 120 | //while(1); 121 | goto *entry; 122 | } 123 | -------------------------------------------------------------------------------- /vga/draw_func.c: -------------------------------------------------------------------------------- 1 | #include "draw_func.h" 2 | #include "font_rawdata.h" 3 | #include "k_stdlib.h" 4 | #include "io.h" 5 | #include "vga.h" 6 | 7 | const int y_res = 320; 8 | 9 | void draw_box() 10 | { 11 | u8 *vb = (u8*)0xa0000; 12 | 13 | for (int x=0 ; x < 320 ; ++x) 14 | for (int y=0 ; y < 200 ; ++y) 15 | { 16 | *(vb + x + 320*y) = 1; // 0: black, 1: blue 17 | } 18 | } 19 | 20 | void draw_box_1(int draw_x, int draw_y, int c) 21 | { 22 | u8 *vb = (u8*)0xa0000; 23 | 24 | for (int x = draw_x ; x < 40+draw_x ; ++x) 25 | for (int y = draw_y ; y < 40+draw_y ; ++y) 26 | { 27 | *(vb + x + 320*y) = c; 28 | } 29 | //void draw_str(); 30 | //draw_str(); 31 | } 32 | 33 | // current only for 320X240 34 | void draw_str(int ox, int oy, u8 color) 35 | { 36 | const u8* image_addr = str; 37 | 38 | for (int y = 0 ; y < hb ; ++y) 39 | { 40 | int xx=0; 41 | for (int x = 0 ; x < wb ; ++x) 42 | { 43 | u8 c = *image_addr; 44 | 45 | for (int i=7 ; i>=0 ; --i, ++xx) 46 | { 47 | if (((c >> i) & 0x1) == 1) 48 | draw_point(ox+xx, oy+y, color); 49 | } 50 | ++image_addr; 51 | } 52 | } 53 | 54 | } 55 | 56 | void draw_char(int dx, int dy, char ch) 57 | { 58 | BOCHS_MB 59 | u8 line=1; 60 | 61 | const u8* image_addr = ch_data; 62 | int org_x=dx; 63 | int org_y=dy; 64 | int cur_x=org_x; 65 | int cur_y=org_y; 66 | u8 *org_vb = (u8*)(0xa0000 + cur_x + cur_y*320);// + dx + dy*320; 67 | u8 *vb = org_vb; 68 | 69 | for (int y = 0 ; y < ch_hb ; ++y) 70 | { 71 | for (int x = 0 ; x < ch_wb ; ++x) 72 | { 73 | u8 c = *image_addr; 74 | 75 | 76 | for (int i=7 ; i>=0 ; --i) 77 | { 78 | if (((c >> i) & 0x1) == 1) 79 | *vb = 7; 80 | else 81 | ;//printf("|"); 82 | //++cur_x; 83 | ++vb; 84 | } 85 | 86 | ++image_addr; 87 | } 88 | ++cur_y; 89 | vb = (u8*)((0xa0000+(320*cur_y)) + org_x); 90 | ++line; 91 | } 92 | } 93 | 94 | #if 1 95 | void draw_bg(int ox, int oy, u8 *pic_raw_data, int w, int h, u8 *palette) 96 | { 97 | u8 *vb = (u8*)0xa0000; 98 | int line=0; 99 | const u8* image_addr = pic_raw_data; 100 | //extern u8 PALETTE[]; 101 | u8 *p = palette; 102 | 103 | for (int i=0 ; i < 256; ++i) 104 | { 105 | set_palette(i, *p, *(p+1), *(p+2)); 106 | p+=3; 107 | } 108 | 109 | 110 | for (int y = 0 ; y < h ; ++y) 111 | { 112 | for (int x = 0 ; x < w ; ++x) 113 | { 114 | u8 c = *image_addr; 115 | draw_point(ox+x, y, c); 116 | //*vb++ = c; 117 | 118 | ++image_addr; 119 | } 120 | //vb = (u8*)(0xa0000+(320*line)); 121 | //++line; 122 | } 123 | } 124 | 125 | void draw_20x12_grid(int x, int y, u8 c) 126 | { 127 | for (int h=0; h < 12 ; ++h) 128 | for (int w=0 ; w < 20 ; ++w) 129 | draw_point(x+w, y+h, c); 130 | } 131 | 132 | void draw_256_grid(void) 133 | { 134 | u8 c=0; 135 | for (int y=0 ; y < 200 ; y+=12) 136 | for (int x=0 ; x < 320 ; x+=20) 137 | draw_20x12_grid(x, y, c++); 138 | 139 | } 140 | 141 | // only for 320X200X256 color 142 | void draw_point(int x, int y, u8 c) 143 | { 144 | u32 vm = 0xa0000; 145 | *((u8*)(vm + x + y*y_res)) = c; 146 | } 147 | 148 | void set_palette(int index, u8 r, u8 g, u8 b) 149 | { 150 | io_out8(PALETTE_MASK,0xff); 151 | io_out8(PALETTE_REGISTER_WR,index); 152 | io_out8(PALETTE_DATA, r); 153 | io_out8(PALETTE_DATA, g); 154 | io_out8(PALETTE_DATA, b); 155 | } 156 | 157 | void draw_8x16_ch(int ox, int oy, u8 ch, u8 color) 158 | { 159 | extern char font[]; 160 | //extern char *font; note: is wrong, so point is diff from array 161 | const u8* image_addr = font + ch *16; 162 | 163 | for (int y = 0 ; y < 16 ; ++y) 164 | { 165 | int xx=0; 166 | for (int x = 0 ; x < 1 ; ++x) 167 | { 168 | u8 c = *image_addr; 169 | 170 | for (int i=7 ; i>=0 ; --i, ++xx) 171 | { 172 | if (((c >> i) & 0x1) == 1) 173 | draw_point(ox+xx, oy+y, color); 174 | } 175 | ++image_addr; 176 | } 177 | } 178 | } 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /c_init_by_boot_loader.s: -------------------------------------------------------------------------------- 1 | .code16 2 | .extern __bss_start__ 3 | .extern __bss_end__ 4 | 5 | .text 6 | .global _start 7 | _start: 8 | mov %cs, %ax 9 | mov %ax, %ds 10 | mov %ax, %es 11 | #movw $0x0, %ax 12 | movw %ax, %ds 13 | mov %ax, %ss 14 | # setup stack 15 | mov $0xfff0, %sp # why not setting 0xffff to %sp, in ms dos, 0xfff0 is ok, 0xffb will get core dump 16 | 17 | # call disp_str 18 | call init_bss_asm 19 | # for bss 20 | # movw $0x0, %ax 21 | # movw %ax, %ds 22 | # call p 23 | call start_c 24 | # call text_test 25 | # call disp_str2 26 | jmp . 27 | #disp_str: 28 | # mov $BootMessage, %ax 29 | # mov %ax,%bp 30 | # mov $16,%cx 31 | # mov $0x1301,%ax 32 | # mov $0x00c,%bx 33 | # mov $0,%dl 34 | # int $0x10 35 | # ret 36 | #BootMessage:.ascii "Hello, c-env world!" 37 | #disp_str2: 38 | # mov $str2, %ax 39 | # mov %ax,%bp 40 | # mov $5,%cx 41 | # mov $0x1301,%ax 42 | # mov $0x00c,%bx 43 | # mov $0,%dl 44 | # int $0x10 45 | # ret 46 | #str2:.ascii "after" 47 | 48 | .globl write_mem8 49 | write_mem8: 50 | pushl %ebp 51 | mov %esp, %ebp 52 | #movw $0xa000, %ax # graphic mode 53 | movw $0xb800, %ax # text mode 54 | movw %ax, %gs 55 | movl 8(%ebp), %ecx; 56 | # mov $0x0, %ecx; 57 | movb 12(%ebp), %al; 58 | movb %al, %gs:(%ecx) 59 | #movb $'A', %gs:(%ecx) 60 | popl %ebp 61 | ret 62 | 63 | 64 | # init bss 65 | init_bss_asm: 66 | movw $__bss_end__, %di /* Destination */ 67 | movw $__bss_start__, %si /* Source */ 68 | # movw $0x0, %ax 69 | # movw %ax, %gs 70 | jmp 2f 71 | 1: 72 | movw %si, %ax 73 | movb $0x1, (%eax) 74 | # movb $0x1, %ds:(%eax) 75 | add $1, %si 76 | 77 | 2: 78 | cmpw %di, %si 79 | jne 1b 80 | ret 81 | 82 | # copy from: write_os/src/chapter3/8/lib.h 83 | # ex: 84 | # asm_memcpy((u8*)0x100, (u8 *)IMAGE_LMA, 512*3); 85 | # copy IMAGE_LMA to 0x7000:0x100 86 | .globl asm_memcpy 87 | asm_memcpy: 88 | pushl %ebp 89 | mov %esp, %ebp 90 | 91 | pushl %esi 92 | pushl %edi 93 | pushl %ecx 94 | 95 | mov $0x7000, %ax 96 | mov %ax, %fs 97 | 98 | mov 8(%ebp), %edi /* Destination */ 99 | mov 12(%ebp), %esi /* Source */ 100 | mov 16(%ebp), %ecx /* Counter */ 101 | MemCpy.1: 102 | cmp $0, %ecx /* Loop counter */ 103 | jz MemCpy.2 104 | movb %ds:(%esi), %al 105 | inc %esi 106 | movb %al, %fs:(%edi) 107 | inc %edi 108 | dec %ecx 109 | jmp MemCpy.1 110 | MemCpy.2: 111 | mov 8(%ebp), %eax 112 | pop %ecx 113 | pop %edi 114 | pop %esi 115 | mov %ebp, %esp 116 | pop %ebp 117 | ret 118 | 119 | .globl asm_absolute_memcpy 120 | # ex: 121 | # asm_absolute_memcpy((u8*)0x100, (u8 *)IMAGE_LMA, 512*3); 122 | # copy IMAGE_LMA to 0x100 123 | asm_absolute_memcpy: 124 | pushl %ebp 125 | mov %esp, %ebp 126 | 127 | pushl %esi 128 | pushl %edi 129 | pushl %ecx 130 | 131 | mov $0, %ax 132 | mov %ax, %fs 133 | 134 | mov 8(%ebp), %edi /* Destination */ 135 | mov 12(%ebp), %esi /* Source */ 136 | mov 16(%ebp), %ecx /* Counter */ 137 | 1: 138 | cmp $0, %ecx /* Loop counter */ 139 | jz 2f 140 | movb %ds:(%esi), %al 141 | inc %esi 142 | movb %al, %fs:(%edi) 143 | inc %edi 144 | dec %ecx 145 | jmp 1b 146 | 2: 147 | mov 8(%ebp), %eax 148 | pop %ecx 149 | pop %edi 150 | pop %esi 151 | mov %ebp, %esp 152 | pop %ebp 153 | ret 154 | 155 | # movw 16(%ebp), %ecx /* Counter */ 156 | #1: 157 | # cmp $0, %ecx /* Loop counter */ 158 | # jz MemCpy.2 159 | # movb %ds:(%esi), %al 160 | # inc %esi 161 | # movb %al, %es:(%edi) 162 | # inc %edi 163 | # dec %ecx 164 | # jmp MemCpy.1 165 | #2: 166 | # mov 8(%ebp), %eax 167 | # pop %ecx 168 | # pop %edi 169 | # pop %esi 170 | # mov %ebp, %esp 171 | # pop %ebp 172 | # ret 173 | 174 | 175 | 176 | #.bss 177 | #_bss_start_:.word __bss_start__ 178 | #_bss_end_:.word __bss_end__ 179 | 180 | .data 181 | #LABEL_STACK: 182 | #.space 512, 0 183 | 184 | 185 | #.section ss 186 | # mov %ax, %es 187 | #.org 510 188 | #.word 0xaa55 189 | 190 | -------------------------------------------------------------------------------- /include/keyboard.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYBOARD_H 2 | #define KEYBOARD_H 3 | 4 | #include "type.h" 5 | #include "tty.h" 6 | 7 | #define KB_NUM 32 8 | #define NR_SCAN_CODES 0x80 9 | #define KEYMAP_COLS 2 10 | 11 | #define PRESS 0 12 | #define RELEASE 1 13 | 14 | // form qt 15 | #define KEY_ESC 0x01000000 16 | #define KEY_TAB 0x01000001 17 | #define KEY_Backtab 0x01000002 18 | #define KEY_BACKSPACE 0x01000003 19 | #define KEY_Return 0x01000004 20 | #define KEY_ENTER 0x01000005 //Typically located on the keypad. 21 | #define KEY_INSERT 0x01000006 22 | #define KEY_DELETE 0x01000007 23 | #define KEY_Pause 0x01000008 //The Pause/Break key (Note: Not anything to do with pausing media) 24 | #define KEY_Print 0x01000009 25 | #define KEY_SysReq 0x0100000a 26 | #define KEY_Clear 0x0100000b 27 | #define KEY_HOME 0x01000010 28 | #define KEY_END 0x01000011 29 | #define KEY_LEFT 0x01000012 30 | #define KEY_UP 0x01000013 31 | #define KEY_RIGHT 0x01000014 32 | #define KEY_DOWN 0x01000015 33 | #define KEY_PAGE_UP 0x01000016 34 | #define KEY_PAGE_DOWN 0x01000017 35 | #define KEY_SHIFT_L 0x01000020 36 | #define KEY_SHIFT_R 0x01000220 37 | #define KEY_CTRL_L 0x01000021 //On Mac OS X, this corresponds to the Command keys. 38 | #define KEY_Meta 0x01000022 //On Mac OS X, this corresponds to the Control keys. On Windows keyboards, this key is mapped to the Windows key. 39 | #define KEY_ALT_L 0x01000023 40 | #define KEY_Alt_R 0x01001103 //On Windows, when the KeyDown event for this key is sent, the Ctrl+Alt modifiers are also set. 41 | #define KEY_CAPSLOCK 0x01000024 42 | #define KEY_NUMLOCK 0x01000025 43 | #define KEY_SCROLL_LOCK 0x01000026 44 | #define KEY_F1 0x01000030 45 | #define KEY_F2 0x01000031 46 | #define KEY_F3 0x01000032 47 | #define KEY_F4 0x01000033 48 | #define KEY_F5 0x01000034 49 | #define KEY_F6 0x01000035 50 | #define KEY_F7 0x01000036 51 | #define KEY_F8 0x01000037 52 | #define KEY_F9 0x01000038 53 | #define KEY_F10 0x01000039 54 | #define KEY_F11 0x0100003a 55 | #define KEY_F12 0x0100003b 56 | #define KEY_F13 0x0100003c 57 | #define KEY_F14 0x0100003d 58 | #define KEY_F15 0x0100003e 59 | #define KEY_F16 0x0100003f 60 | #define KEY_F17 0x01000040 61 | #define KEY_F18 0x01000041 62 | #define KEY_F19 0x01000042 63 | #define KEY_F20 0x01000043 64 | #define KEY_F21 0x01000044 65 | #define KEY_F22 0x01000045 66 | #define KEY_F23 0x01000046 67 | #define KEY_F24 0x01000047 68 | #define KEY_F25 0x01000048 69 | #define KEY_F26 0x01000049 70 | #define KEY_F27 0x0100004a 71 | #define KEY_F28 0x0100004b 72 | #define KEY_F29 0x0100004c 73 | #define KEY_F30 0x0100004d 74 | #define KEY_F31 0x0100004e 75 | #define KEY_F32 0x0100004f 76 | #define KEY_F33 0x01000050 77 | #define KEY_F34 0x01000051 78 | #define KEY_F35 0x01000052 79 | #define KEY_Super_L 0x01000053 80 | #define Key_Super_R 0x01000054 81 | #define Key_Menu 0x01000055 82 | #define Key_Hyper_L 0x01000056 83 | #define Key_Hyper_R 0x01000057 84 | #define Key_Help 0x01000058 85 | #define Key_Direction_L 0x01000059 86 | #define Key_Direction_R 0x01000060 87 | #define KEY_MINUS 0x01000160 88 | #define KEY_MID 0x01000161 89 | #define KEY_PLUS 0x01000162 90 | #define KEY_DOT 0x01000163 91 | 92 | #define SCANCODE_MODE 0 93 | #define KEYCODE_MODE 1 94 | #define ASCII_MODE 2 95 | 96 | typedef struct KeyboardBuf_ 97 | { 98 | u8 *head; 99 | u8 *tail; 100 | u32 count; // buf count, less than KB_NUM 101 | u8 buf[KB_NUM]; 102 | }KeyboardBuf; 103 | 104 | typedef struct KeyStatus_ 105 | { 106 | int key; 107 | int scan_code[10]; 108 | u8 press; // press or release 109 | }KeyStatus; 110 | 111 | int init_keyboard(void); 112 | u8 get_byte_from_kb_buf(void); 113 | int parse_scan_code(KeyStatus *key_status, int keyborad_mode); 114 | int keyboard_read(Tty *tty); 115 | int lookup_key(u8 scan_code, u8 col); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /include/elf.h: -------------------------------------------------------------------------------- 1 | /* copy from leeos/chapter8/part2/elf.h */ 2 | /* 3 | elf.h: 4 | Copyright (C) 2009 david leels 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | 21 | #ifndef __ELF_H__ 22 | #define __ELF_H__ 23 | 24 | typedef unsigned int elf32_addr; 25 | typedef unsigned int elf32_word; 26 | typedef signed int elf32_sword; 27 | typedef unsigned short elf32_half; 28 | typedef unsigned int elf32_off; 29 | 30 | 31 | typedef struct elf32_ehdr_{ 32 | unsigned char e_ident[16]; /* 魔数和相关信息 */ 33 | elf32_half e_type; /* 目标文件类型 */ 34 | elf32_half e_machine; /* 硬件体系 */ 35 | elf32_word e_version; /* 目标文件版本 */ 36 | elf32_addr e_entry; /* 程序进入点 */ 37 | elf32_off e_phoff; /* 程序头部偏移量 */ 38 | elf32_off e_shoff; /* 节头部偏移量 */ 39 | elf32_word e_flags; /* 处理器特定标志 */ 40 | elf32_half e_ehsize; /* elf头部长度 */ 41 | elf32_half e_phentsize; /* 程序头部中一个条目的长度 */ 42 | elf32_half e_phnum; /* 程序头部条目个数 */ 43 | elf32_half e_shentsize; /* 节头部中一个条目的长度 */ 44 | elf32_half e_shnum; /* 节头部条目个数 */ 45 | elf32_half e_shstrndx; /* 节头部字符表索引 */ 46 | }Elf32Ehdr; 47 | 48 | typedef struct elf32_phdr_{ 49 | elf32_word p_type; /* 段类型 */ 50 | elf32_off p_offset; /* 段位置相对于文件开始处的偏移量 */ 51 | elf32_addr p_vaddr; /* 段在内存中的地址 */ 52 | elf32_addr p_paddr; /* 段的物理地址 */ 53 | elf32_word p_filesz; /* 段在文件中的长度 */ 54 | elf32_word p_memsz; /* 段在内存中的长度 */ 55 | elf32_word p_flags; /* 段的标记 */ 56 | elf32_word p_align; /* 段在内存中对齐标记 */ 57 | }Elf32Phdr; 58 | 59 | /*definition of elf class*/ 60 | #define ELFCLASSNONE 0 61 | #define ELFCLASS32 1 62 | #define ELFCLASS64 2 63 | #define CHECK_ELF_CLASS(p) ((p)->e_ident[4]) 64 | #define CHECK_ELF_CLASS_ELFCLASS32(p) (CHECK_ELF_CLASS(p)==ELFCLASS32) 65 | 66 | /*definition of elf data*/ 67 | #define ELFDATANONE 0 68 | #define ELFDATA2LSB 1 69 | #define ELFDATA2MSB 2 70 | #define CHECK_ELF_DATA(p) ((p)->e_ident[5]) 71 | #define CHECK_ELF_DATA_LSB(p) (CHECK_ELF_DATA(p)==ELFDATA2LSB) 72 | 73 | /*elf type*/ 74 | #define ET_NONE 0 75 | #define ET_REL 1 76 | #define ET_EXEC 2 77 | #define ET_DYN 3 78 | #define ET_CORE 4 79 | #define ET_LOPROC 0xff00 80 | #define ET_HIPROC 0xffff 81 | #define CHECK_ELF_TYPE(p) ((p)->e_type) 82 | #define CHECK_ELF_TYPE_EXEC(p) (CHECK_ELF_TYPE(p)==ET_EXEC) 83 | 84 | /*elf machine*/ 85 | #define EM_NONE 0 86 | #define EM_M32 1 87 | #define EM_SPARC 2 88 | #define EM_386 3 89 | #define EM_68k 4 90 | #define EM_88k 5 91 | #define EM_860 7 92 | #define EM_MIPS 8 93 | #define EM_ARM 40 94 | #define CHECK_ELF_MACHINE(p) ((p)->e_machine) 95 | #define CHECK_ELF_MACHINE_ARM(p) (CHECK_ELF_MACHINE(p)==EM_ARM) 96 | 97 | /*elf version*/ 98 | #define EV_NONE 0 99 | #define EV_CURRENT 1 100 | #define CHECK_ELF_VERSION(p) ((p)->e_ident[6]) 101 | #define CHECK_ELF_VERSION_CURRENT(p) (CHECK_ELF_VERSION(p)==EV_CURRENT) 102 | 103 | #define ELF_FILE_CHECK(hdr) ((((hdr)->e_ident[0])==0x7f)&&\ 104 | (((hdr)->e_ident[1])=='E')&&\ 105 | (((hdr)->e_ident[2])=='L')&&\ 106 | (((hdr)->e_ident[3])=='F')) 107 | 108 | 109 | #define PT_NULL 0 110 | #define PT_LOAD 1 111 | #define PT_DYNAMIC 2 112 | #define PT_INTERP 3 113 | #define PT_NOTE 4 114 | #define PT_SHLIB 5 115 | #define PT_PHDR 6 116 | #define PT_LOPROC 0x70000000 117 | #define PT_HIPROC 0x7fffffff 118 | #define CHECK_PT_TYPE(p) ((p)->p_type) 119 | #define CHECK_PT_TYPE_LOAD(p) (CHECK_PT_TYPE(p)==PT_LOAD) 120 | 121 | //ref : /usr/src/linux-headers-2.6.32-38-generic/include/linux/elf.h 122 | #define ELFMAG "\177ELF" 123 | #define SELFMAG 4 124 | #define SHF_ALLOC 0x2 125 | 126 | typedef struct { 127 | elf32_word sh_name; 128 | elf32_word sh_type; 129 | elf32_word sh_flags; 130 | elf32_addr sh_addr; 131 | elf32_off sh_offset; 132 | elf32_word sh_size; 133 | elf32_word sh_link; 134 | elf32_word sh_info; 135 | elf32_word sh_addralign; 136 | elf32_word sh_entsize; 137 | } Elf32_Shdr; 138 | 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /include/process.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESS_H 2 | #define PROCESS_H 3 | 4 | #include "type.h" 5 | #include "protect.h" 6 | #include "k_string.h" 7 | 8 | #define LDT_SIZE 2 9 | #define NR_TASKS 3 10 | #define NR_PROCS 32 11 | #define NR_NATIVE_PROCS 4 12 | 13 | #define TASK_TTY 0 14 | #define TASK_SYS 1 15 | #define TASK_MM 2 16 | 17 | 18 | #define STACK_SIZE_TESTA 0x8000 19 | #define TASK_STACK 0x8000 20 | #define STACK_SIZE_TOTAL (TASK_STACK*(NR_TASKS+NR_NATIVE_PROCS)) 21 | #define SELECTOR_LDT_FIRST (INDEX_LDT_FIRST*8) 22 | 23 | #define PRIVILEGE_TASK 1 24 | 25 | #define RPL_TASK 1 26 | #define RPL_USER 3 27 | 28 | #define TASK_NAME_LEN 32 29 | 30 | extern int k_reenter; 31 | 32 | typedef struct StackFrame_ 33 | { 34 | u32 gs; 35 | u32 fs; 36 | u32 es; 37 | u32 ds; 38 | u32 edi; 39 | u32 esi; 40 | u32 ebp; 41 | u32 kernel_esp; 42 | u32 ebx; 43 | u32 edx; 44 | u32 ecx; 45 | u32 eax; 46 | u32 retaddr; 47 | u32 eip; 48 | u32 cs; 49 | u32 eflags; 50 | u32 esp; 51 | u32 ss; 52 | }StackFrame; 53 | 54 | typedef struct Mess1_ 55 | { 56 | int m1i1; 57 | int m1i2; 58 | int m1i3; 59 | int m1i4; 60 | }Mess1; 61 | 62 | typedef struct Mess2_ 63 | { 64 | int m2i1; 65 | int m2i2; 66 | int m2i3; 67 | int m2i4; 68 | }Mess2; 69 | 70 | typedef struct Mess3_ 71 | { 72 | int m3i1; 73 | int m3i2; 74 | int m3i3; 75 | int m3i4; 76 | u64 m3l1; 77 | u64 m3l2; 78 | void * m3p1; 79 | void * m3p2; 80 | }Mess3; 81 | 82 | typedef struct Message_ 83 | { 84 | int source; 85 | int type; 86 | union 87 | { 88 | Mess1 m1; 89 | Mess2 m2; 90 | Mess3 m3; 91 | }u; 92 | }Message; 93 | 94 | #define RETVAL u.m3.m3i1 95 | #define PID u.m3.m3i2 96 | #define STATUS u.m3.m3i1 97 | #define PATHNAME u.m3.m3p1 98 | #define NAME_LEN u.m3.m3i2 99 | #define BUF u.m3.m3p2 100 | #define BUF_LEN u.m3.m3i3 101 | 102 | 103 | typedef struct Process_ 104 | { 105 | StackFrame regs; 106 | u16 ldt_sel; 107 | Descriptor ldt[LDT_SIZE]; 108 | u32 pid; 109 | //const char *p_name; 110 | int tty_index; // use which tty 111 | 112 | int p_flags; 113 | 114 | Message *msg; 115 | int p_recvfrom; 116 | int p_sendto; 117 | int has_int_msg; 118 | u32 p_parent; 119 | //u32 org_esp; 120 | struct Process_ *q_sending; 121 | struct Process_ *next_sending; 122 | int exit_status; 123 | char name[TASK_NAME_LEN]; 124 | 125 | }Process; 126 | 127 | typedef void (*TaskAddr)(void); 128 | 129 | typedef struct Task_ 130 | { 131 | TaskAddr init_eip; 132 | u32 stack_size; 133 | char name[TASK_NAME_LEN]; 134 | }Task; 135 | 136 | 137 | typedef struct Tss_ 138 | { 139 | u32 backlink; 140 | u32 esp0; 141 | u32 ss0; 142 | u32 esp1; 143 | u32 ss1; 144 | u32 esp2; 145 | u32 ss2; 146 | u32 cr3; 147 | u32 eip; 148 | u32 flags; 149 | u32 eax; 150 | u32 ecx; 151 | u32 edx; 152 | u32 ebx; 153 | u32 esp; 154 | u32 ebp; 155 | u32 esi; 156 | u32 edi; 157 | u32 es; 158 | u32 cs; 159 | u32 ss; 160 | u32 ds; 161 | u32 fs; 162 | u32 gs; 163 | u32 ldt; 164 | u32 trap; 165 | u32 iobase; 166 | }Tss; 167 | 168 | extern Process proc_table[]; 169 | extern u8 task_stack[]; 170 | extern Process *ready_process; 171 | extern Tss tss; 172 | 173 | void init_proc(void); 174 | void schedule(void); 175 | 176 | int ldt_seg_linear(Process *p, int ldt_index); 177 | 178 | #define proc2pid(x) (x - proc_table) 179 | 180 | void* va2la(int pid, void* va); 181 | 182 | //int msg_send(struct Process_* current, int dest, struct Message_* m); 183 | //int msg_receive(struct Process_* current, int src, struct Message_* m); 184 | int msg_send(Process* current, int dest, Message* m); 185 | int msg_receive(Process* current, int src, Message* m); 186 | int send_recv(int function, int src_dest, Message *msg); 187 | 188 | #define SEND 1 189 | #define RECEIVE 2 190 | #define BOTH 3 /* BOTH = (SEND | RECEIVE) */ 191 | 192 | #define ANY (NR_TASKS + NR_PROCS + 10) 193 | #define NO_TASK (NR_TASKS + NR_PROCS + 20) 194 | #define INTERRUPT -10 195 | 196 | /* ipc */ 197 | #define SEND 1 198 | #define RECEIVE 2 199 | #define BOTH 3 /* BOTH = (SEND | RECEIVE) */ 200 | 201 | /* Process */ 202 | #define SENDING 0x02 /* set when proc trying to send */ 203 | #define RECEIVING 0x04 /* set when proc trying to recv */ 204 | #define WAITING 0x08 205 | #define HANGING 0x10 206 | #define FREE_SLOT 0x20 207 | 208 | 209 | static inline void reset_msg(Message *m) 210 | { 211 | p_asm_memset(m, 0, sizeof(Message)); 212 | } 213 | 214 | int exec(u8 *start); 215 | 216 | #define HARD_INT 1 217 | #define GET_TICKS 2 218 | #define FORK 3 219 | #define SYSCALL_RET 4 220 | #define EXIT 5 221 | #define WAIT 6 222 | #define EXEC 7 223 | 224 | #endif 225 | -------------------------------------------------------------------------------- /syscall.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "asm_syscall.h" 3 | #include "k_assert.h" 4 | #include "k_stdlib.h" 5 | #include "process.h" 6 | #include "type.h" 7 | #include "vga.h" 8 | #include "tty.h" 9 | #include "irq.h" 10 | 11 | typedef void* SystemCall; 12 | 13 | #if 0 14 | char* s32_itoa(int n, char* str, int radix); 15 | void s32_print(const u8 *s, u8 *vb); 16 | void s32_print_int(int i, u8 *vb, int radix); 17 | void clear_line(u8 line_no); 18 | void loop_delay(int time); 19 | #endif 20 | 21 | #ifdef IPC 22 | int get_ticks(void) 23 | { 24 | Message msg; 25 | reset_msg(&msg); 26 | msg.type = GET_TICKS; 27 | send_recv(BOTH, TASK_SYS, &msg); 28 | return msg.RETVAL; 29 | } 30 | 31 | int fork(void) 32 | { 33 | Message msg; 34 | msg.type = FORK; 35 | send_recv(BOTH, TASK_MM, &msg); 36 | 37 | return msg.PID; 38 | } 39 | 40 | void exit(int s) 41 | { 42 | Message msg; 43 | msg.type = EXIT; 44 | msg.STATUS = s; 45 | send_recv(BOTH, TASK_MM, &msg); 46 | assert(msg.type == SYSCALL_RET); 47 | } 48 | 49 | int wait(int *s) 50 | { 51 | Message msg; 52 | msg.type = WAIT; 53 | send_recv(BOTH, TASK_MM, &msg); 54 | *s = msg.STATUS; 55 | return (msg.PID == NO_TASK ? -1 : msg.PID); 56 | } 57 | 58 | int execl(const char *path) 59 | { 60 | Message msg; 61 | msg.type = EXEC; 62 | msg.PATHNAME = (void*)path; 63 | msg.NAME_LEN = s_strlen(path); 64 | msg.BUF = 0; 65 | msg.BUF_LEN = 0; 66 | 67 | send_recv(BOTH, TASK_MM, &msg); 68 | assert(msg.type == SYSCALL_RET); 69 | 70 | return msg.RETVAL; 71 | } 72 | 73 | #endif 74 | 75 | int sys_get_ticks(void) 76 | { 77 | extern u32 ticks; 78 | 79 | #if 0 80 | static int p=0; 81 | s32_print("+", (u8*)(0xb8000+p)); 82 | p += 2; 83 | p = (p % 160); 84 | #endif 85 | return ticks; 86 | } 87 | 88 | int sys_set_vga_mode(void) 89 | { 90 | switch_vga_mode(); 91 | return 0; 92 | } 93 | 94 | int sys_write(char *buf, int len, int useless, Process *proc) 95 | { 96 | tty_write(&tty_table[proc->tty_index], buf, len); 97 | return 0; 98 | } 99 | 100 | int sys_sendrec(int function, int src_dest, Message *m, Process *p) 101 | { 102 | assert(k_reenter == 0); 103 | assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) || src_dest == ANY || src_dest == INTERRUPT); 104 | 105 | int ret = 0; 106 | int caller = proc2pid(p); 107 | Message *msg = (Message *)va2la(caller, m); 108 | msg->source = caller; 109 | 110 | assert(msg->source != src_dest); 111 | 112 | if (function == SEND) 113 | { 114 | ret = msg_send(p, src_dest, m); 115 | if (ret != 0) 116 | return ret; 117 | } 118 | else if (function == RECEIVE) 119 | { 120 | ret = msg_receive(p, src_dest, m); 121 | if (ret != 0) 122 | return ret; 123 | } 124 | else 125 | { 126 | panic("invalid function:"); 127 | } 128 | return 0; 129 | } 130 | 131 | int sys_app_print(int unused1, int unused2, char *s, Process *proc) 132 | { 133 | const char *p="fail string"; 134 | if (k_reenter == 0) // ring 1 ~ 3 135 | p = va2la(proc2pid(proc), s); 136 | else if (k_reenter > 0) // ring 0 137 | p = s; 138 | 139 | s32_print(p, (u8*)(0xb8000+160*20)); 140 | return 0; 141 | } 142 | 143 | int sys_printk(int unused1, int unused2, char *s, Process *proc) 144 | { 145 | const char *p; 146 | char ch; 147 | char reenter_err[] = "?k_reenter is incorrect for unknown reason"; 148 | reenter_err[0] = MAG_CH_PANIC; 149 | 150 | if (k_reenter == 0) // ring 1 ~ 3 151 | p = va2la(proc2pid(proc), s); 152 | else if (k_reenter > 0) // ring 0 153 | p = s; 154 | else 155 | p = reenter_err; 156 | 157 | if ((*p == MAG_CH_PANIC) || (*p == MAG_CH_ASSERT && ready_process < &proc_table[NR_TASKS])) 158 | { 159 | disable_int(); 160 | char *v = (char*)V_MEM_BASE; 161 | const char *q=p+1; 162 | 163 | while(v <(char *)(V_MEM_BASE + V_MEM_SIZE)) 164 | { 165 | *v++ = *q++; 166 | *v++ = RED_CHAR; 167 | if (!*q) 168 | { 169 | while(((int)v - V_MEM_BASE) % (SCR_WIDTH * 16)) 170 | { 171 | ++v; 172 | *v++ = GRAY_CHAR; 173 | } 174 | q = p+1; 175 | } 176 | 177 | } 178 | __asm__ __volatile__("hlt"); 179 | } 180 | //int x=0, y=5; 181 | while((ch = *p++) != 0) 182 | { 183 | if (ch == MAG_CH_PANIC || ch == MAG_CH_ASSERT) 184 | continue; 185 | //s32_console_print_char_xy(tty_table[proc->tty_index].console, ch, x, y); 186 | s32_console_print_char(tty_table[proc->tty_index].console, ch); 187 | #if 0 188 | ++x; 189 | if (x > 80) 190 | { 191 | ++y; 192 | x=0; 193 | } 194 | #endif 195 | } 196 | return 0; 197 | 198 | } 199 | 200 | SystemCall sys_call_table[NR_SYS_CALL] = {sys_get_ticks, sys_set_vga_mode, sys_write, sys_sendrec, sys_printk, sys_app_print}; 201 | 202 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | #CFLAGS = -fno-stack-protector -std=c99 -march=i686 -ffreestanding -Wall -g 2 | #CFLAGS = -fno-stack-protector -ffreestanding -fno-builtin -g 3 | 4 | include rule.mk 5 | 6 | FS_SRC = fs/romfs.c fs/vfs.c 7 | FS_OBJS = fs/romfs.o fs/vfs.o 8 | 9 | all: boot.img 10 | 11 | boot.img: p_kernel.elf 12 | git clone https://github.com/descent/write_os.git ; cd write_os/src/chapter2/2 ; make 13 | cp write_os/src/chapter2/2/boot.img . 14 | script/cp2img.sh 15 | @echo "" 16 | @echo "type 'qemu-system-i386 -fda boot.img' for test" 17 | 18 | 19 | kloaderp.bin: 20 | (cd kernel_loader; make) 21 | 22 | boot1.img: c_init.bin 23 | dd if=$< of=$@ bs=512 count=1 24 | dd if=/dev/zero of=$@ skip=1 seek=1 bs=512 count=2879 25 | 26 | c_init.bin: c_init.elf 27 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 28 | 29 | c_init.elf: c_init.o b.o bss.lds 30 | ld $(LDFLAGS) -nostdlib -g -o $@ -Tbss.lds c_init.o b.o 31 | c_init.o: c_init.s 32 | as $(ASFLAGS) -o $@ $< 33 | b.o: b.c 34 | #gcc -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -Iinclude -I../include -Os -c $< 35 | gcc -std=c99 -fno-stack-protector -m32 -ffreestanding -fno-builtin -g -Iinclude -I../include -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables -Os -c $< 36 | b.s: b.c 37 | gcc -S $(CFLAGS) -c $< 38 | 39 | c_init_by_boot_loader.bin: c_init_by_boot_loader.elf 40 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 41 | 42 | c_init_by_boot_loader.elf: c_init_by_boot_loader.o b_by_bootloader.o switch_vga_mode.o bss_dos.lds 43 | ld $(LDFLAGS) -nostdlib -g -o $@ -Tbss_dos.lds c_init_by_boot_loader.o b_by_bootloader.o switch_vga_mode.o 44 | c_init_by_boot_loader.o: c_init_by_boot_loader.s 45 | as $(ASFLAGS) -o $@ $< 46 | b_by_bootloader.o: b_by_bootloader.c 47 | gcc $(CFLAGS) -c $< 48 | b_by_bootloader.s: b_by_bootloader.c 49 | gcc -S $(CFLAGS) $< 50 | switch_vga_mode.o: switch_vga_mode.c 51 | gcc $(CFLAGS) -c $< 52 | switch_vga_mode.s: switch_vga_mode.c 53 | gcc -S $(CFLAGS) $< 54 | 55 | kloader.bin: kernel_loader.elf 56 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 57 | 58 | kernel_loader.elf: c_init_by_boot_loader.o kernel_loader.o 59 | ld $(LDFLAGS) -nostdlib -g -o $@ -Tbss_dos.lds $^ 60 | 61 | kernel.bin: kernel.elf 62 | objcopy -R .pdr -R .comment -R.note -S -O binary $< $@ 63 | kernel.elf: kernel.o 64 | ld $(LDFLAGS) -nostdlib -g -o $@ -Tbss_dos.lds $^ 65 | kernel.o: kernel.s 66 | as $(ASFLAGS) -o $@ $< 67 | 68 | 69 | p_kernel.elf: p_kernel.o io/k_stdio.o asm_func.o asm_syscall.o $(FS_OBJS) vga/set_mode_p.o vga/draw_func.o vga/font_rawdata.o tty/tty.o tty/keyboard.o tty/console.o clock.o start.o process.o storage.o syscall.o io/k_stdio_k.o k_assert.o systask.o test-romfs.o mm/mm.o k_stdlib.o 70 | ld $(LDFLAGS) -nostdlib -M -g -o $@ -Tk.ld $^ > $@.map && cp $@ $@.gdb && strip $@ 71 | 72 | p_kernel.o: p_kernel.s 73 | as --32 -o $@ $< 74 | 75 | test-romfs.o: rom.fs 76 | objcopy -I binary -O elf32-i386 -B i386 --prefix-sections '.romfs' $< test-romfs.o 77 | #rom.fs: 78 | 79 | #start.o: start.c io.h clock.h protect.h process.h syscall.h \ 80 | # include/storage.h include/type.h include/romfs.h include/k_string.h \ 81 | # include/endian.h 82 | # gcc $(CFLAGS) -c $< 83 | 84 | start.s: start.c type.h protect.h process.h 85 | gcc $(CFLAGS) -o $@ -S $< 86 | 87 | #process.o: process.c process.h include/type.h protect.h 88 | # gcc $(CFLAGS) -c $< 89 | # 90 | #clock.o: clock.c clock.h include/type.h process.h protect.h 91 | # gcc $(CFLAGS) -c $< 92 | # 93 | #storage.o: storage.c include/storage.h include/type.h 94 | # gcc $(CFLAGS) -c $< 95 | 96 | asm_func.o: asm_func.s 97 | as --32 -o $@ $< 98 | 99 | asm_func.s: asm_func.S 100 | gcc $(CFLAGS) -o $@ -E $< 101 | 102 | asm_syscall.o: asm_syscall.s 103 | as --32 -o $@ $< 104 | asm_syscall.s: asm_syscall.S include/syscall.h process_const.h 105 | gcc $(CFLAGS) -o $@ -E $< 106 | 107 | #syscall.o: syscall.c syscall.h 108 | # gcc $(CFLAGS) -c $< 109 | 110 | $(FS_OBJS):$(FS_SRC) 111 | (cd fs; make) 112 | mm/mm.o: mm 113 | (cd mm; make mm.o) 114 | vga/set_mode_p.o: vga 115 | (cd vga; make set_mode_p.o) 116 | 117 | vga/draw_func.o: vga 118 | (cd vga; make draw_func.o) 119 | 120 | vga/font_rawdata.o: vga 121 | (cd vga; make font_rawdata.o) 122 | 123 | io/k_stdio.o: io 124 | (cd io; make k_stdio.o) 125 | io/k_stdio_k.o: io 126 | (cd io; make k_stdio_k.o) 127 | tty/keyboard.o: tty 128 | (cd tty; make keyboard.o) 129 | tty/console.o: tty 130 | (cd tty; make console.o) 131 | tty/tty.o: tty 132 | (cd tty; make tty.o) 133 | sources = clock.c start.c process.c storage.c syscall.c k_assert.c systask.c k_stdlib.c 134 | include $(sources:.c=.d) 135 | #C_OBJS = $(sources:.c=.o) 136 | C_OBJS = clock.o start.o process.o storage.o syscall.o 137 | 138 | #o: 139 | # echo $(C_OBJS) 140 | 141 | rom.fs: genromfs romfs 142 | ./others/genromfs -d romfs/ -f rom.fs 143 | 144 | genromfs: 145 | if [ ! -d "romfs" ]; then echo "mkdir romfs" ; mkdir romfs ; fi 146 | (cd others; make) 147 | 148 | .PHONE: clean distclean kloaderp.bin 149 | 150 | clean: 151 | rm -rf *.o *.elf *.bin asm_syscall.s romfs ; #(cd kernel_loader; make clean) 152 | find . -name "*.d" -exec rm -f {} \; 153 | distclean: 154 | rm -rf *.img write_os 155 | -------------------------------------------------------------------------------- /tty/tty.c: -------------------------------------------------------------------------------- 1 | #include "tty.h" 2 | #include "k_stdio.h" 3 | #include "k_stdlib.h" 4 | #include "console.h" 5 | #include "keyboard.h" 6 | #include "k_assert.h" 7 | 8 | #define TRUE 1 9 | #define FALSE (!TRUE) 10 | 11 | Tty tty_table[TTY_NUM]; 12 | 13 | static int cur_tty_index = 0; 14 | 15 | int select_tty(int tty_index) 16 | { 17 | int ret =0; 18 | 19 | if ( 0 <= cur_tty_index && cur_tty_index < TTY_NUM) 20 | cur_tty_index = tty_index; 21 | else 22 | ret = -1; 23 | 24 | //s32_print_int(tty_table[cur_tty_index].console->vm_start, (u8*)(0xb8000+160*1), 16); 25 | 26 | int org_x, org_y; 27 | get_xy(tty_table[cur_tty_index].console, &org_x, &org_y); 28 | 29 | set_xy(tty_table[cur_tty_index].console, 0, 0); 30 | s32_console_print_str(tty_table[cur_tty_index].console, "simple os tty "); 31 | 32 | switch (cur_tty_index) 33 | { 34 | case 0: 35 | s32_console_print_char(tty_table[cur_tty_index].console, '1'); 36 | break; 37 | case 1: 38 | s32_console_print_char(tty_table[cur_tty_index].console, '2'); 39 | break; 40 | case 2: 41 | s32_console_print_char(tty_table[cur_tty_index].console, '3'); 42 | break; 43 | default: 44 | break; 45 | } 46 | s32_console_print_str(tty_table[cur_tty_index].console, "\r\nfake login: "); 47 | s32_console_print_str(tty_table[cur_tty_index].console, "\r\n\r\n"); 48 | set_xy(tty_table[cur_tty_index].console, org_x, org_y); 49 | u16 cur_console_vm_start = (tty_table[cur_tty_index].console->vm_start-0xb8000)/2; 50 | set_video_start_addr(cur_console_vm_start); 51 | 52 | 53 | //set_cursor(cur_console_vm_start + tty_table[cur_tty_index].console->cur_x + tty_table[cur_tty_index].console->cur_y*80); 54 | set_cursor(cur_console_vm_start + org_x + org_y*80); 55 | return ret; 56 | } 57 | 58 | int init_tty(Tty *tty) 59 | { 60 | //panic("in tty"); 61 | tty->inbuf_count = 0; 62 | tty->inbuf_head = tty->inbuf_tail = tty->inbuf; 63 | 64 | u8 tty_index = tty - tty_table; 65 | tty->console = console_table + tty_index; 66 | tty->ready = 1; 67 | 68 | return 0; 69 | } 70 | 71 | int is_current_tty(Tty *tty) 72 | { 73 | return (tty == &tty_table[cur_tty_index]); 74 | #if 0 75 | if (cur_tty_index == (tty - tty_table)/sizeof(Tty)) 76 | return TRUE; 77 | else 78 | return FALSE; 79 | #endif 80 | } 81 | 82 | int get_data_from_tty_buf(Tty *tty) 83 | { 84 | if (tty->inbuf_count) 85 | { 86 | u8 ch = *(tty->inbuf_tail); 87 | if (tty->inbuf_tail == tty->inbuf + TTY_IN_BYTES_NUM) 88 | tty->inbuf_tail = tty->inbuf; 89 | --tty->inbuf_count; 90 | return ch; 91 | } 92 | else 93 | return -1; 94 | } 95 | 96 | int parse_key(Tty *tty, KeyStatus *key_status) 97 | { 98 | static u8 keymap_col=0; 99 | 100 | int scan_code = get_data_from_tty_buf(tty); 101 | switch (scan_code) 102 | { 103 | case -1: 104 | break; 105 | case 0xe1: 106 | break; 107 | case 0xe0: 108 | scan_code = get_data_from_tty_buf(tty); 109 | key_status->key = lookup_key(scan_code & 0x7f, keymap_col); 110 | key_status->press = ((scan_code & 0x80) ? RELEASE: PRESS); 111 | break; 112 | default: 113 | key_status->key = lookup_key(scan_code & 0x7f, keymap_col); 114 | key_status->press = ((scan_code & 0x80) ? RELEASE: PRESS); 115 | break; 116 | } 117 | } 118 | 119 | void tty_do_read(Tty *tty) 120 | { 121 | if(is_current_tty(tty)) 122 | { 123 | keyboard_read(tty); // call put_key 124 | //KeyStatus key_status; 125 | 126 | //parse_key(tty, &key_status); 127 | } 128 | } 129 | 130 | void tty_do_write(Tty *tty) 131 | { 132 | if (tty->inbuf_count) 133 | { 134 | u32 ch = *(tty->inbuf_tail); 135 | ++(tty->inbuf_tail); 136 | if (tty->inbuf_tail == tty->inbuf + TTY_IN_BYTES_NUM) 137 | tty->inbuf_tail = tty->inbuf; 138 | 139 | --tty->inbuf_count; 140 | //s32_console_print_char(tty->console, ch); 141 | switch (ch) 142 | { 143 | case KEY_ENTER: 144 | s32_console_print_char(tty_table[cur_tty_index].console, '\r'); 145 | s32_console_print_char(tty_table[cur_tty_index].console, '\n'); 146 | break; 147 | default: 148 | s32_console_print_char(tty_table[cur_tty_index].console, ch); 149 | break; 150 | } 151 | } 152 | } 153 | 154 | void task_tty(void) 155 | { 156 | Tty *tty; 157 | 158 | init_console(); 159 | 160 | for (tty = tty_table ; tty < tty_table + TTY_NUM ; ++tty) 161 | { 162 | init_tty(tty); 163 | } 164 | select_tty(0); 165 | 166 | static int i=0; 167 | while(1) 168 | { 169 | //assert(0); 170 | //panic("in tty"); 171 | s32_print_int(i, (u8*)(0xb8000+160*23), 10); 172 | ++i; 173 | for (tty = tty_table ; tty < tty_table + TTY_NUM ; ++tty) 174 | { 175 | if (tty->ready == 1) 176 | { 177 | tty_do_read(tty); 178 | tty_do_write(tty); 179 | } 180 | } 181 | } 182 | } 183 | 184 | int put_key(Tty *tty, u32 key) 185 | { 186 | if (tty->inbuf_count < TTY_IN_BYTES_NUM) 187 | { 188 | s32_put_char(key, (u8*)(0xb8000+160*20)); 189 | *(tty->inbuf_head) = key; 190 | ++tty->inbuf_head; 191 | if (tty->inbuf_head == tty->inbuf+TTY_IN_BYTES_NUM) 192 | tty->inbuf_head = tty->inbuf; 193 | ++tty->inbuf_count; 194 | } 195 | } 196 | 197 | void tty_write(Tty *tty, char *buf, int len) 198 | { 199 | for (int i=0 ; i < len ; ++i) 200 | if (tty->ready == 1) 201 | s32_console_print_char(tty->console, buf[i]); 202 | 203 | } 204 | -------------------------------------------------------------------------------- /io/k_stdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel and kernel loader share io function 3 | */ 4 | 5 | #include "type.h" 6 | #include "k_stdio.h" 7 | #include "console.h" 8 | 9 | u8 *cur_vb = (u8*)0xb8000+160; 10 | 11 | 12 | // prefix s32 means simple, 32bit code (in x86 protected mode) 13 | void s32_put_char(u8 ch, u8 *vb) 14 | { 15 | *vb = ch; 16 | } 17 | 18 | // text mode screen 25 * 80 19 | void s32_print(const u8 *s, u8 *vb) 20 | { 21 | while(*s) 22 | { 23 | s32_put_char(*s, vb); 24 | ++s; 25 | vb+=2; 26 | } 27 | cur_vb = vb; 28 | if ((int)cur_vb >= 0xb8000+160*24) 29 | cur_vb = (u8*)0xb8000+160; 30 | } 31 | 32 | // sign version 33 | char* s32_itoa_s(int n, char* str, int radix) 34 | { 35 | char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 36 | char* p=str; 37 | char* head=str; 38 | //int radix = 10; 39 | 40 | // if(!p || radix < 2 || radix > 36) 41 | // return p; 42 | if (n==0) 43 | { 44 | *p++='0'; 45 | *p=0; 46 | return str; 47 | } 48 | if (radix == 10 && n < 0) 49 | { 50 | *p++='-'; 51 | n= -n; 52 | } 53 | while(n) 54 | { 55 | *p++=digit[n%radix]; 56 | //s32_put_char(*(p-1), (u8*)(0xb8000+80*2)); 57 | n/=radix; 58 | } 59 | *p=0; 60 | #if 1 61 | for (--p; head < p ; ++head, --p) 62 | { 63 | char temp=*head; 64 | if (*(p-1) != '-') 65 | { 66 | *head=*p; 67 | *p=temp; 68 | } 69 | } 70 | #endif 71 | return str; 72 | } 73 | 74 | // no sign version 75 | char* s32_itoa(u32 n, char* str, int radix) 76 | { 77 | char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 78 | char* p=str; 79 | char* head=str; 80 | //int radix = 10; 81 | 82 | // if(!p || radix < 2 || radix > 36) 83 | // return p; 84 | if (n==0) 85 | { 86 | *p++='0'; 87 | *p=0; 88 | return str; 89 | } 90 | if (radix == 10 && n < 0) 91 | { 92 | *p++='-'; 93 | n= -n; 94 | } 95 | while(n) 96 | { 97 | *p++=digit[n%radix]; 98 | //s32_put_char(*(p-1), (u8*)(0xb8000+80*2)); 99 | n/=radix; 100 | } 101 | *p=0; 102 | #if 1 103 | for (--p; head < p ; ++head, --p) 104 | { 105 | char temp=*head; 106 | if (*(p-1) != '-') 107 | { 108 | *head=*p; 109 | *p=temp; 110 | } 111 | } 112 | #endif 113 | return str; 114 | } 115 | 116 | void s32_print_int(int i, u8 *vb, int radix) 117 | { 118 | u8 str[12]=""; 119 | u8 *str_ptr = str; 120 | 121 | str_ptr = s32_itoa(i, str_ptr, radix); 122 | s32_print(str_ptr, vb); 123 | } 124 | 125 | void clear_line(u8 line_no) 126 | { 127 | u8* vb = (u8*)0xb8000 + 160*line_no; 128 | 129 | for (int x = 0; x < 80; ++x) 130 | { 131 | *vb++ = 0x20; 132 | *vb++ = WHITE; 133 | } 134 | } 135 | 136 | void clear() 137 | { 138 | u8* vb = (u8*)0xb8000; 139 | const u8 row=25; 140 | 141 | for (int x = 0; x < 80*row ; ++x) 142 | { 143 | *vb++ = 0x20; 144 | *vb++ = WHITE; 145 | } 146 | } 147 | 148 | // preifx p means protected 149 | void p_dump_u8(u8 *buff, int len) 150 | { 151 | void h2c(u8 hex, u8 ch[2]); 152 | 153 | u8 *vb = (u8*)0xb8000; 154 | int line=24; 155 | 156 | for (int i=0 ; i < len ; ++i) 157 | { 158 | u8 c[4]=""; 159 | //if (i%16==0) 160 | // s32_print("\r\n", vb); 161 | u8 h=*(buff+i); 162 | c[3]=0; 163 | c[2]=0x20; // space 164 | h2c(h, c); 165 | s32_print(c, vb); 166 | vb+=6; 167 | } 168 | #if 0 169 | clear_line(line); 170 | s32_print("len:", (u8*)(0xb8000+160*line)); 171 | s32_print_int(len, (u8*)(0xb8000+160*line+12*2), 16); 172 | #endif 173 | } 174 | 175 | void h2c(u8 hex, u8 ch[2]) 176 | { 177 | u8 l = hex >> 4; 178 | 179 | if ( 0<= l && l <= 9) 180 | { 181 | ch[0]=l+0x30; 182 | } 183 | else 184 | { 185 | ch[0]=l+0x41-0xa; //a 186 | ch[0]=l+0x61-0xa; // A 187 | } 188 | 189 | l = hex & 0x0f; 190 | 191 | if ( 0<= l && l <= 9) 192 | { 193 | ch[1]=l+0x30; 194 | } 195 | else 196 | { 197 | ch[1]=l+0x41-0xa; //a 198 | ch[1]=l+0x61-0xa; // A 199 | } 200 | } 201 | 202 | int s32_vsprintf(char *str_buf, const char *fmt, char * ap) 203 | { 204 | char *p = str_buf; 205 | u8 *arg = ap; 206 | 207 | for (; *fmt ; ++fmt) 208 | { 209 | if (*fmt != '%') 210 | { 211 | *p++ = *fmt; 212 | continue; 213 | } 214 | ++fmt; 215 | u32 arg_content = *((u32*)arg); 216 | 217 | switch (*fmt) 218 | { 219 | case 'c': 220 | { 221 | *p++ = (char)arg_content; 222 | break; 223 | } 224 | case 'd': 225 | { 226 | u8 str[12]=""; 227 | s32_itoa(arg_content, str, 10); 228 | 229 | char *str_ptr = str; 230 | while(*str_ptr) 231 | *p++ = *str_ptr++; 232 | break; 233 | } 234 | case 'x': 235 | { 236 | u8 str[12]=""; 237 | s32_itoa(arg_content, str, 16); 238 | 239 | char *str_ptr = str; 240 | while(*str_ptr) 241 | *p++ = *str_ptr++; 242 | break; 243 | } 244 | case 's': 245 | { 246 | char *str_ptr = (char *)arg_content; 247 | while(*str_ptr) 248 | *p++ = *str_ptr++; 249 | break; 250 | } 251 | default: 252 | break; 253 | } 254 | arg+=4; 255 | 256 | } // end for (char *p = buf; *fmt ; ++fmt, ++i) 257 | *p='\0'; 258 | return p-str_buf - 1; 259 | } 260 | 261 | int s32_sprintf(char *str_buf, const char *fmt, ...) 262 | { 263 | int i=1; 264 | char *p = str_buf; 265 | 266 | for (; *fmt ; ++fmt) 267 | { 268 | if (*fmt != '%') 269 | { 270 | *p++ = *fmt; 271 | continue; 272 | } 273 | ++fmt; 274 | u8 *arg = (u8 *)(&fmt + i); // nst argument address 275 | u32 arg_content = *((u32*)arg); 276 | 277 | switch (*fmt) 278 | { 279 | case 'd': 280 | { 281 | u8 str[12]=""; 282 | s32_itoa(arg_content, str, 10); 283 | 284 | char *str_ptr = str; 285 | while(*str_ptr) 286 | *p++ = *str_ptr++; 287 | break; 288 | } 289 | case 'x': 290 | { 291 | u8 str[12]=""; 292 | s32_itoa(arg_content, str, 16); 293 | 294 | char *str_ptr = str; 295 | while(*str_ptr) 296 | *p++ = *str_ptr++; 297 | break; 298 | } 299 | case 's': 300 | { 301 | char *str_ptr = (char *)arg_content; 302 | while(*str_ptr) 303 | *p++ = *str_ptr++; 304 | break; 305 | } 306 | default: 307 | break; 308 | } 309 | ++i; // point to next argument 310 | 311 | } // end for (char *p = buf; *fmt ; ++fmt, ++i) 312 | *p='\0'; 313 | return p-str_buf - 1; 314 | } 315 | -------------------------------------------------------------------------------- /tty/console.c: -------------------------------------------------------------------------------- 1 | #include "irq.h" 2 | #include "type.h" 3 | #include "vga.h" 4 | #include "io.h" 5 | #include "console.h" 6 | #include "k_stdio.h" 7 | #include "k_stdlib.h" 8 | #include "draw_func.h" 9 | #include "font_rawdata.h" 10 | 11 | static int cur_console_index=0; 12 | 13 | u8 *text_vb = (u8*)0xb8000; 14 | u8 text_fg; 15 | u8 text_bg; 16 | u16 cur_pos=0; 17 | u32 cur_x; 18 | u32 cur_y; 19 | 20 | Console console_table[CONSOLE_NUM]; 21 | 22 | int init_console() 23 | { 24 | Console *console; 25 | 26 | for (int i=0 ; i < CONSOLE_NUM - 1; ++i) 27 | { 28 | console = &console_table[i]; 29 | console->cur_vm = console->vm_start = 0xb8000 + i*VIDEO_RAM_SIZE; 30 | console->cur_x = 0; 31 | console->cur_y = 2; 32 | console->type = TEXT_CONSOLE; 33 | } 34 | 35 | Console *g_console = &console_table[CONSOLE_NUM-1]; 36 | g_console->type = GRAPHIC_CONSOLE; 37 | g_console->cur_vm = g_console->vm_start = 0xa0000; 38 | return 0; 39 | } 40 | 41 | int select_console(int console_index) 42 | { 43 | int ret =0; 44 | 45 | if ( 0 <= console_index && console_index < TTY_NUM) 46 | cur_console_index = console_index; 47 | else 48 | ret = -1; 49 | return ret; 50 | } 51 | 52 | void set_cursor(u16 pos) 53 | { 54 | disable_int(); 55 | io_out8(CRTC_ADDR, CURSOR_H); 56 | io_out8(CRTC_DATA, (pos >> 8) & 0xff); 57 | 58 | io_out8(CRTC_ADDR, CURSOR_L); 59 | io_out8(CRTC_DATA, pos & 0xff); 60 | enable_int(); 61 | } 62 | 63 | void set_video_start_addr(u16 addr) 64 | { 65 | disable_int(); 66 | io_out8(CRTC_ADDR, START_ADDR_H); 67 | io_out8(CRTC_DATA, (addr >> 8) & 0xff); 68 | io_out8(CRTC_ADDR, START_ADDR_L); 69 | io_out8(CRTC_DATA, addr & 0xff); 70 | enable_int(); 71 | } 72 | 73 | // prefix s32 means simple, 32bit code (in x86 protected mode) 74 | // this version don't specify video address 75 | // for console io 76 | void s32_print_char(u8 ch) 77 | { 78 | switch (ch) 79 | { 80 | case '\r': 81 | //cur_x = cur_x - (cur_x % 80); 82 | cur_x = 0; 83 | text_vb = (u8*)((u32)text_vb - (((u32)text_vb-0xb8000) % 160)); 84 | cur_pos = (((u32)text_vb - 0xb8000)/2); 85 | s32_print_int(cur_pos, (u8*)(0xb8000+160*1 + 18*2+20), 16); 86 | break; 87 | case '\n': 88 | text_vb+=160; 89 | cur_pos += 80; 90 | s32_print_int(cur_pos, (u8*)(0xb8000+160*1 + 18*2+40), 16); 91 | ++cur_y; 92 | break; 93 | case 0x20 ... 0x7e: // ascii printable char. gnu extension: I don't want use gnu extension, but it is very convenience. 94 | *text_vb = ch; 95 | *(text_vb+1) = (text_fg|text_bg); 96 | text_vb+=2; 97 | ++cur_x; 98 | ++cur_pos; 99 | break; 100 | default: 101 | break; 102 | } 103 | 104 | set_cursor(cur_pos); 105 | s32_print_int(cur_pos, (u8*)(0xb8000+160*1 + 18*2+60), 16); 106 | clear_line(18); 107 | s32_print_int(cur_x, (u8*)(0xb8000+160*18 + 23*2+40), 10); 108 | s32_print_int(cur_y, (u8*)(0xb8000+160*18 + 23*2+60), 10); 109 | if (cur_y >= 25 ) 110 | set_video_start_addr(80*(cur_y - 24)); 111 | } 112 | 113 | void s32_print_str(const u8* str) 114 | { 115 | while(*str) 116 | s32_print_char(*str++); 117 | } 118 | 119 | void s32_set_text_color(u8 fg, u8 bg) 120 | { 121 | text_fg=fg; 122 | text_bg=bg; 123 | } 124 | 125 | void s32_console_print_char_xy(Console *console, u8 ch, int x, int y) 126 | { 127 | console->cur_x = x; 128 | console->cur_y = y; 129 | s32_console_print_char(console, ch); 130 | } 131 | 132 | void s32_console_print_str_xy(Console *console, const u8 *str, int x, int y) 133 | { 134 | for (int i=0 ; str[i] != 0 ; ++i) 135 | { 136 | s32_console_print_char_xy(console, str[i], x++, y); 137 | } 138 | } 139 | 140 | void set_xy(Console *console, int x, int y) 141 | { 142 | console->cur_x = x; 143 | console->cur_y = y; 144 | } 145 | 146 | void get_xy(Console *console, int *x, int *y) 147 | { 148 | *x = console->cur_x; 149 | *y = console->cur_y; 150 | } 151 | 152 | void s32_console_print_char(Console *console, u8 ch) 153 | { 154 | 155 | if (console->type == GRAPHIC_CONSOLE) 156 | { 157 | //BOCHS_MB 158 | //draw_char(console->cur_x, console->cur_y, ch); 159 | draw_8x16_ch(console->cur_x, console->cur_y, ch, 5); 160 | console->cur_x += 8; 161 | if (console->cur_x >= 320) 162 | { 163 | console->cur_x = 0; 164 | console->cur_y += 16; 165 | } 166 | #if 1 167 | if (ch == '`') 168 | { 169 | static u8 odd=0; 170 | extern u8 bg_raw_data[]; 171 | extern int bg_w; 172 | extern int bg_h; 173 | extern u8 palette_data[]; 174 | 175 | extern u8 os_bg_raw_data[]; 176 | extern int os_bg_w; 177 | extern int os_bg_h; 178 | extern u8 os_palette_data[]; 179 | draw_256_grid(); 180 | switch (odd) 181 | { 182 | case 0: 183 | { 184 | draw_bg(120, 0, bg_raw_data, bg_w, bg_h, palette_data); 185 | break; 186 | } 187 | case 1: 188 | { 189 | draw_bg(0, 0, os_bg_raw_data, os_bg_w, os_bg_h, os_palette_data); 190 | break; 191 | } 192 | case 2: 193 | { 194 | draw_bg(0, 0, pe_320_180_256_bmp, pe_320_180_256_wb, pe_320_180_256_hb, pe_320_180_256_palette_data); 195 | break; 196 | } 197 | } 198 | odd = (odd+1) % 3; 199 | } 200 | #endif 201 | return; 202 | } 203 | 204 | u8 *console_vb = (u8*)console->cur_vm; 205 | u32 vm = console->vm_start; 206 | //u8 *console_vb = (u8*)(0xb8000); 207 | //s32_put_char(ch, (u8*)(0xb8000+160*19)); 208 | //if (console->cur_y >= ((VIDEO_RAM_SIZE/4000) * 25) ) 209 | if (console->cur_y >= 50) 210 | return; 211 | 212 | switch (ch) 213 | { 214 | case '\r': 215 | console->cur_x = 0; 216 | break; 217 | case '\n': 218 | ++console->cur_y; 219 | break; 220 | case 0x20 ... 0x7e: // ascii printable char. gnu extension: I don't want use gnu extension, but it is very convenience. 221 | //*console_vb = ch; 222 | //*(console_vb+1) = (text_fg|text_bg); 223 | *((u8 *)(vm + (console->cur_x + console->cur_y * 80)*2)) = ch; 224 | *((u8 *)(vm + (console->cur_x + console->cur_y * 80)*2)+1) = 7; // WHITE 225 | ++console->cur_x; 226 | if (console->cur_x >= 80) 227 | { 228 | console->cur_x = 0; 229 | ++console->cur_y; 230 | } 231 | break; 232 | default: 233 | break; 234 | } 235 | console_vb = (console->cur_x + console->cur_y*80)*2 + console->vm_start; 236 | 237 | if (console->cur_y >= 25 ) 238 | set_video_start_addr(80*(console->cur_y - 24)); 239 | set_cursor((console->vm_start - 0xb8000)/2 + console->cur_x + console->cur_y * 80); 240 | console->cur_vm = (u32)console_vb; 241 | } 242 | 243 | void s32_console_print_str(Console *console, const u8 *str) 244 | { 245 | for (int i=0 ; str[i] != 0 ; ++i) 246 | { 247 | s32_console_print_char(console, str[i]); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /vga/set_mode.S: -------------------------------------------------------------------------------- 1 | # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/MAIN.ASM 2 | # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/USAGE.TXT 3 | # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/README.TXT 4 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 5 | #=- Currently supported Video Modes: -= Mode Number =- 6 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 7 | #=- 03H -=- 320 x 200 x 256 -= 03H =- 8 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 9 | #=- 10H -=- 640 x 350 x 16 -= 10H =- 10 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 11 | #=- 12H -=- 640 x 480 x 16 -= 12H =- 12 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 13 | #=- 13H -=- 320 x 200 x 256 -= 13H =- 14 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 15 | #=- Chain 4 -=- unchained 320 x 200 x 256 -= 14H =- 16 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 17 | #=- Mode X -=- unchained 320 x 240 x 256 -= 15H =- 18 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 19 | #=- Mode A -=- unchained 320 x 400 x 256 -= 16H =- 20 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 21 | #=- Mode B -=- unchained 360 x 480 x 256 -= 17H =- 22 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 23 | #=- Mode C -=- 640 x 400 x 16 -= 18H =- 24 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 25 | 26 | .equ ATTRCON_ADDR , 0x03C0 27 | .equ MISC_ADDR , 0x03C2 28 | .equ VGAENABLE_ADDR , 0x03C3 29 | .equ SEQ_ADDR , 0x03C4 30 | .equ GRACON_ADDR , 0x03CE 31 | .equ CRTC_ADDR , 0x03D4 32 | .equ STATUS_ADDR , 0x03DA 33 | 34 | 35 | #.code32 36 | .code16 37 | .text 38 | .global begin 39 | begin: 40 | #MOV $MODE12H, %si 41 | xchg %bx, %bx #bochs magic break point 42 | mov %cs, %ax 43 | mov %ax, %ds 44 | mov %ax, %es 45 | mov %ax, %ss 46 | 47 | MOV $MODE10H, %si 48 | CALL SETMODE 49 | call SET_OUT 50 | # draw screen 51 | pushw $12 52 | CALL CLEAR10H 53 | 54 | # Set Mode 03h 55 | #SET03H: 56 | # MOV $MODE03H, %si 57 | # CALL SETMODE 58 | # Must do this to ensure proper text 59 | # CALL SETFONT 60 | # JMP SET_OUT 61 | 62 | 63 | jmp . 64 | 65 | 66 | CLEAR10H: 67 | PUSH %BP 68 | MOV %SP, %bp 69 | 70 | MOV $0xA000, %ax 71 | MOV %AX, %es 72 | XOR %DI,%DI 73 | MOV $7000, %cx 74 | 75 | CLEAR_LOOP2: 76 | MOV $0x03CE, %dx 77 | MOV $0x0FF08, %ax 78 | OUT %AX, %dx 79 | 80 | MOV $0, %eax 81 | #XCHG DWORD PTR ES:[DI],EAX 82 | xchgl %EAX, %es:(%di) 83 | 84 | MOV $0x03C4, %dx 85 | #MOV AH,BYTE PTR [BP+4] 86 | movb 4(%BP), %ah 87 | MOV $2, %AL 88 | OUT %AX, %dx 89 | 90 | #MOV DWORD PTR ES:[DI],0FFFFFFFFH 91 | movl $0xFFFFFFFF, %es:(%di) 92 | 93 | MOV $0x0F02, %ax 94 | OUT %AX, %dx 95 | 96 | MOV $0x03CE, %dx 97 | MOV $0x0FF08, %ax 98 | OUT %AX, %dx 99 | 100 | ADD $4, %DI 101 | LOOP CLEAR_LOOP2 102 | 103 | POP %BP 104 | RET 105 | 106 | 107 | 108 | 109 | SETMODE: 110 | # Send MISC regs 111 | MOV $MISC_ADDR, %dx 112 | MOV (%si), %AL 113 | OUT %al, %DX 114 | call iodelay 115 | INC %SI 116 | 117 | MOV $STATUS_ADDR, %dx 118 | MOV (%si), %AL 119 | OUT %AL, %dx 120 | call iodelay 121 | INC %SI 122 | 123 | # Send SEQ regs 124 | MOV $0, %CX 125 | REG_LOOP: 126 | MOV $SEQ_ADDR, %dx 127 | MOV %CL, %al 128 | OUT %AL, %dx 129 | call iodelay 130 | 131 | MOV $SEQ_ADDR, %dx 132 | INC %DX 133 | MOV (%si), %AL 134 | OUT %AL, %dx 135 | call iodelay 136 | INC %SI 137 | INC %CX 138 | CMP $5, %cl 139 | JL REG_LOOP 140 | 141 | # Clear Protection bits 142 | MOV $0x0E, %ah 143 | MOV 0x11, %al 144 | AND 0x7F, %ah 145 | MOV $CRTC_ADDR, %dx 146 | OUT %AX, %dx 147 | call iodelay 148 | 149 | # Send CRTC regs 150 | MOV $0, %cx 151 | REG_LOOP2: 152 | MOV $CRTC_ADDR, %dx 153 | MOV %CL, %al 154 | OUT %AL, %dx 155 | call iodelay 156 | 157 | MOV $CRTC_ADDR, %dx 158 | INC %DX 159 | MOV (%si), %AL 160 | OUT %AL, %dx 161 | call iodelay 162 | 163 | INC %SI 164 | INC %CX 165 | CMP $25, %CL 166 | JL REG_LOOP2 167 | 168 | # Send GRAPHICS regs 169 | MOV $0, %CX 170 | REG_LOOP3: 171 | MOV $GRACON_ADDR, %dx 172 | MOV %CL, %al 173 | OUT %AL, %dx 174 | call iodelay 175 | 176 | MOV $GRACON_ADDR, %dx 177 | INC %DX 178 | MOV (%si), %AL 179 | OUT %AL, %dx 180 | call iodelay 181 | 182 | INC %SI 183 | INC %CX 184 | CMP $9, %CL 185 | JL REG_LOOP3 186 | 187 | MOV $STATUS_ADDR, %dx 188 | IN %DX, %al 189 | call iodelay 190 | 191 | # Send ATTRCON regs 192 | MOV $0, %cx 193 | REG_LOOP4: 194 | MOV $ATTRCON_ADDR, %dx 195 | IN %DX, %ax 196 | 197 | MOV %CL, %al 198 | OUT %AL, %dx 199 | call iodelay 200 | 201 | MOV (%si), %AL 202 | OUT %AL, %dx 203 | call iodelay 204 | 205 | INC %SI 206 | INC %CX 207 | CMP $21, %CL 208 | JL REG_LOOP4 209 | 210 | MOV $0x20, %al 211 | OUT %AL, %dx 212 | call iodelay 213 | RET 214 | #SETMODE ENDP 215 | SET_OUT: 216 | CALL SETPALETTE 217 | #POP %BP 218 | RET 219 | 220 | iodelay: 221 | nop 222 | nop 223 | nop 224 | nop 225 | ret 226 | 227 | SETPALETTE: 228 | # Address of the 6-byte array 229 | MOV $PALETTE, %di 230 | 231 | MOV $0, %ECX 232 | PAL_LOOP: 233 | MOV %CX, %ax 234 | # Send color 235 | MOV $0x03C8, %dx 236 | OUT %AL, %dx 237 | 238 | # Write R value 239 | MOV $0x03C9, %dx 240 | movb (%DI), %al 241 | OUT %AL, %dx 242 | 243 | # Write G value 244 | MOV $0x03C9, %dx 245 | movb 1(%DI), %al 246 | OUT %AL, %dx 247 | 248 | # Write B value 249 | MOV $0x03C9, %dx 250 | movb 2(%DI), %al 251 | OUT %AL, %dx 252 | 253 | ADD $3, %di 254 | INC %CX 255 | CMP $16, %CX 256 | JLE PAL_LOOP 257 | 258 | RET 259 | 260 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 261 | #=- VGA register variables for the various videomodes -= 262 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 263 | 264 | #if 0 265 | MODE03H: 266 | .byte 0x67,0x00,0x03,0x00,0x03,0x00,0x02 267 | .byte 0x5F,0x4F,0x50,0x82,0x55,0x81,0x0BF,0x1F,0x00,0x4F,0x0E,0x0F,0x00,0x00,0x00,0x00 268 | .byte 0x9C,0x0E,0x8F,0x28,0x01,0x96,0x0B9,0x0A3,0x0FF 269 | .byte 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,0x0FF 270 | .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F 271 | .byte 0x0C,0x00,0x0F,0x08,0x00 272 | #endif 273 | 274 | 275 | MODE10H: 276 | .byte 0xA3,0x00,0x03,0x01,0x0F,0x00,0x06 277 | .byte 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0BF,0x1F,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00 278 | .byte 0x83,0x85,0x5D,0x28,0x0F,0x63,0x0BA,0x0E3,0x0FF 279 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,0x0FF 280 | .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F 281 | .byte 0x01,0x00,0x0F,0x00,0x00 282 | 283 | MODE12H: 284 | .byte 0x0E3, 0x00, 0x03, 0x01, 0x0F, 0x00, 0x06 285 | .byte 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x59 286 | .byte 0xEA,0x8C,0x0DF,0x28,0x00,0x0E7,0x04,0x0E3,0x0FF 287 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,0x0FF 288 | .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F 289 | .byte 0x01,0x00,0x0F,0x00,0x00 290 | 291 | PALETTE: 292 | .byte 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42, 42, 0, 0 293 | .byte 42, 0, 42, 42, 21, 0, 42, 42, 42, 21, 21, 21, 21, 21, 63, 21, 63, 21 294 | .byte 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63 295 | 296 | -------------------------------------------------------------------------------- /mm/mm.c: -------------------------------------------------------------------------------- 1 | #include "mm.h" 2 | #include "protect.h" 3 | #include "k_stdio.h" 4 | #include "k_string.h" 5 | #include "k_assert.h" 6 | #include "elf.h" 7 | #include "vfs.h" 8 | 9 | extern Message mm_msg; 10 | 11 | u32 memory_used; 12 | // 0000 0000 13 | // 0000 0000 14 | // 0000 0000 15 | // 0000 0000 16 | // alloc 512kb, total managed memroy is 32*152kb = 16Mb 17 | 18 | u32 mm_start; 19 | u32 memsize_mb; 20 | u32 memsize; 21 | 22 | u32 io_load_eflags(void); 23 | void io_store_eflags(u32 eflg); 24 | u32 load_cr0(void); 25 | void store_cr0(u32 cr0); 26 | 27 | int mm_init(void) 28 | { 29 | memsize = memtest(0x00400000, 0x2000000); 30 | mm_start = memsize - 16*1024*1024; 31 | } 32 | 33 | int find_free_area(void) 34 | { 35 | for (int i=0 ; i < 32 ; ++i) 36 | { 37 | if (((memory_used >> i) & 1) == 0) 38 | { 39 | memory_used |= (1<p_flags == FREE_SLOT) 131 | break; 132 | 133 | int child_pid = i; 134 | 135 | assert(p == &proc_table[child_pid]); 136 | assert(child_pid >= NR_TASKS + NR_NATIVE_PROCS); 137 | 138 | if (i == NR_TASKS + NR_PROCS) /* no free slot */ 139 | return -1; 140 | assert(i < NR_TASKS + NR_PROCS); 141 | 142 | int pid = mm_msg.source; 143 | u16 child_ldt_sel = p->ldt_sel; 144 | *p = proc_table[pid]; 145 | p->ldt_sel = child_ldt_sel; 146 | p->p_parent = pid; 147 | s32_sprintf(p->name, "%s_%d", proc_table[pid].name, child_pid); 148 | 149 | Descriptor *ppd; 150 | 151 | ppd = &proc_table[pid].ldt[LDT_CODE]; 152 | 153 | u32 caller_T_base = reassembly(ppd->base_high, 24, ppd->base_mid, 16, ppd->base_low); 154 | u32 caller_T_limit = reassembly(0, 0, (ppd->limit_high_attr2 & 0xF), 16, ppd->limit_low); 155 | u32 caller_T_size = ((caller_T_limit + 1) * ((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ? 4096 : 1)); 156 | 157 | ppd = &proc_table[pid].ldt[LDT_DATA]; 158 | u32 caller_D_S_base = reassembly(ppd->base_high, 24, ppd->base_mid, 16, ppd->base_low); 159 | u32 caller_D_S_limit = reassembly(0, 0, (ppd->limit_high_attr2 & 0xF), 16, ppd->limit_low); 160 | u32 caller_D_S_size = ((caller_T_limit + 1) * ((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ? 4096 : 1)); 161 | 162 | assert((caller_T_base == caller_D_S_base ) && (caller_T_limit == caller_D_S_limit) && (caller_T_size == caller_D_S_size )); 163 | 164 | u8* child_base = (u8*)alloc_mem(); 165 | child_base = (u8*)(0xa00000); 166 | caller_T_size = 0x100000; 167 | //p_asm_memcpy(child_base, (void*)caller_T_base, caller_T_size); 168 | //p_asm_memcpy(child_base+0x100000, (void*)caller_T_base+0x100000, 0x100000); 169 | p_asm_memcpy(child_base+0x100000, (void*)caller_T_base+0x100000, caller_T_size); 170 | 171 | #if 0 172 | init_descriptor(&p->ldt[LDT_CODE], (u32)child_base, (PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT, DA_LIMIT_4K | DA_32 | DA_C | PRIVILEGE_USER << 5); 173 | init_descriptor(&p->ldt[LDT_DATA], (u32)child_base, (PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT, DA_LIMIT_4K | DA_32 | DA_DRW | PRIVILEGE_USER << 5); 174 | #else 175 | u32 test_base = (u32)child_base; 176 | u32 test_limit = 0x400-1; 177 | init_descriptor(&p->ldt[LDT_CODE], test_base, test_limit, DA_LIMIT_4K | DA_32 | DA_C | PRIVILEGE_USER << 5); 178 | init_descriptor(&p->ldt[LDT_DATA], test_base, test_limit, DA_LIMIT_4K | DA_32 | DA_DRW | PRIVILEGE_USER << 5); 179 | #endif 180 | mm_msg.PID = child_pid; 181 | 182 | #if 1 183 | // invoke child process 184 | Message m; 185 | m.type = SYSCALL_RET; 186 | m.RETVAL = 0; 187 | m.PID = 0; 188 | send_recv(SEND, child_pid, &m); 189 | #endif 190 | int x=0; // for debug 191 | 192 | return 0; 193 | } 194 | 195 | void cleanup(Process * proc) 196 | { 197 | Message msg2parent; 198 | msg2parent.type = SYSCALL_RET; 199 | msg2parent.PID = proc2pid(proc); 200 | msg2parent.STATUS = proc->exit_status; 201 | send_recv(SEND, proc->p_parent, &msg2parent); 202 | 203 | proc->p_flags = FREE_SLOT; 204 | 205 | } 206 | 207 | #define INIT 3 208 | void do_exit(int status) 209 | { 210 | int pid = mm_msg.source; 211 | int parent_pid = proc_table[pid].p_parent; 212 | Process * p = &proc_table[pid]; 213 | 214 | #if 0 215 | MESSAGE msg2fs; 216 | msg2fs.type = EXIT; 217 | msg2fs.PID = pid; 218 | send_recv(BOTH, TASK_FS, &msg2fs); 219 | #endif 220 | //free_mem(pid); 221 | 222 | p->exit_status = status; 223 | //p->exit_status = 9; 224 | 225 | if (proc_table[parent_pid].p_flags & WAITING) 226 | { 227 | proc_table[parent_pid].p_flags &= ~WAITING; 228 | cleanup(&proc_table[pid]); 229 | 230 | } 231 | else 232 | { 233 | proc_table[parent_pid].p_flags |= HANGING; 234 | } 235 | 236 | for (int i=0 ; i < (NR_TASKS + NR_PROCS); i++) 237 | { 238 | if (proc_table[i].p_parent == pid) 239 | { 240 | proc_table[i].p_parent == INIT; 241 | if ((proc_table[INIT].p_flags & WAITING) && (proc_table[i].p_flags & HANGING)) 242 | { 243 | proc_table[INIT].p_flags &= ~WAITING; 244 | cleanup(&proc_table[i]); 245 | 246 | } 247 | 248 | } 249 | } 250 | } 251 | 252 | void do_wait(void) 253 | { 254 | int pid = mm_msg.source; 255 | 256 | int i; 257 | int children = 0; 258 | Process* p_proc = proc_table; 259 | for (i = 0; i < NR_TASKS + NR_PROCS; i++,p_proc++) 260 | { 261 | if (p_proc->p_parent == pid) 262 | { 263 | children++; 264 | if (p_proc->p_flags & HANGING) 265 | { 266 | cleanup(p_proc); 267 | return; 268 | } 269 | } 270 | } 271 | 272 | if (children) 273 | { 274 | /* has children, but no child is HANGING */ 275 | proc_table[pid].p_flags |= WAITING; 276 | } 277 | else 278 | { 279 | /* no child at all */ 280 | Message msg; 281 | msg.type = SYSCALL_RET; 282 | msg.PID = NO_TASK; 283 | send_recv(SEND, pid, &msg); 284 | } 285 | } 286 | 287 | 288 | void do_execl(void) 289 | { 290 | /* get parameters from the message */ 291 | int name_len = mm_msg.NAME_LEN; /* length of filename */ 292 | int src = mm_msg.source; /* caller proc nr. */ 293 | assert(name_len < MAX_PATH); 294 | 295 | #if 0 296 | char pathname[MAX_PATH]; 297 | p_asm_memcpy((void*)va2la(TASK_MM, pathname), (void*)va2la(src, mm_msg.PATHNAME), name_len); 298 | pathname[name_len] = 0; /* terminate the string */ 299 | #endif 300 | 301 | INode *inode = fs_type[ROMFS]->namei(fs_type[ROMFS], "echo"); // get super block infomation 302 | int addr = fs_type[ROMFS]->get_daddr(inode); 303 | u8 *buf = (u8*)alloc_mem(); 304 | fs_type[ROMFS]->device->dout(fs_type[ROMFS]->device, buf, addr, inode->dsize); 305 | 306 | Elf32Ehdr *elf_header = (Elf32Ehdr*)buf; 307 | Elf32Phdr *elf_pheader = (Elf32Phdr*)((u8 *)buf + elf_header->e_phoff); 308 | u32 entry = elf_header->e_entry; 309 | 310 | for (int i=0 ; i < elf_header->e_phnum; ++i) 311 | { 312 | if (CHECK_PT_TYPE_LOAD(elf_pheader)) 313 | { 314 | p_asm_memcpy((u8*)va2la(src,elf_pheader->p_vaddr), va2la(TASK_MM, buf+(elf_pheader->p_offset)), elf_pheader->p_filesz); 315 | } 316 | ++elf_pheader; 317 | } 318 | free_mem(buf); 319 | 320 | /* setup eip & esp */ 321 | proc_table[src].regs.eip = entry; 322 | //proc_table[src].regs.esp = PROC_IMAGE_SIZE_DEFAULT - PROC_ORIGIN_STACK; 323 | 324 | } 325 | 326 | -------------------------------------------------------------------------------- /fs/romfs.c: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | #include "endian.h" 3 | #include "romfs.h" 4 | #include "vfs.h" 5 | #include "k_string.h" 6 | #include "k_stdio.h" 7 | #include "k_stdlib.h" 8 | #include "mm.h" 9 | 10 | INode *romfs_namei(SuperBlock *sb, char *dir); 11 | u32 romfs_get_daddr(INode *node); 12 | 13 | SuperBlock romfs_sb = 14 | { 15 | .namei = romfs_namei, 16 | .get_daddr = romfs_get_daddr, 17 | .fs_name = "romfs", 18 | }; 19 | 20 | int romfs_init(void) 21 | { 22 | int ret; 23 | 24 | //romfs_sb.namei = romfs_namei; 25 | //romfs_sb.get_daddr = romfs_get_daddr; 26 | 27 | ret = register_file_system(&romfs_sb, ROMFS); 28 | romfs_sb.device = storage[RAMDISK]; 29 | return ret; 30 | } 31 | 32 | RomFsHeader* print_romfs_entry(int begin_print_line, u32 *offset, u8 *buf, u8 is_print) 33 | { 34 | int line = begin_print_line; 35 | u32 next_offset = *offset; 36 | 37 | RomFsHeader *rom_fs_header; 38 | rom_fs_header = (RomFsHeader*)(buf + next_offset); 39 | 40 | if (is_print) 41 | { 42 | clear_line(line); 43 | s32_print("nextfh: ", (u8*)(0xb8000+160*line)); 44 | s32_print_int(be32tole32(rom_fs_header->u.header8.nextfh), (u8*)(0xb8000+160*line + 10*2), 16); 45 | ++line; 46 | 47 | clear_line(line); 48 | s32_print("spec: ", (u8*)(0xb8000+160*line)); 49 | s32_print_int(be32tole32(rom_fs_header->u.header8.spec), (u8*)(0xb8000+160*line + 10*2), 16); 50 | ++line; 51 | 52 | clear_line(line); 53 | s32_print("size: ", (u8*)(0xb8000+160*line)); 54 | s32_print_int(be32tole32(rom_fs_header->size), (u8*)(0xb8000+160*line + 10*2), 16); 55 | ++line; 56 | 57 | clear_line(line); 58 | s32_print("checksum: ", (u8*)(0xb8000+160*line)); 59 | s32_print_int(be32tole32(rom_fs_header->checksum), (u8*)(0xb8000+160*line + 10*2), 16); 60 | ++line; 61 | } 62 | next_offset +=16; // file name offset, skip rom_fs_header 63 | u32 fn_len = s_strlen(buf+next_offset); 64 | //u32 fn_len = s_strlen(rom_fs_header->fn); 65 | 66 | if (is_print) 67 | { 68 | clear_line(line); 69 | s32_print("fn_len: ", (u8*)(0xb8000+160*line)); 70 | s32_print_int(fn_len, (u8*)(0xb8000+160*line + 10*2), 10); 71 | ++line; 72 | 73 | clear_line(line); 74 | s32_print("fn: ", (u8*)(0xb8000+160*line)); 75 | s32_print(buf+next_offset, (u8*)(0xb8000+160*line+10*2)); 76 | 77 | switch (get_file_type(be32tole32(rom_fs_header->u.header8.nextfh))) 78 | { 79 | case HARD_LINK: 80 | s32_print("hard link", (u8*)(0xb8000+160*line)+ 15*2); 81 | break; 82 | case DIRECTORY: 83 | s32_print("dir", (u8*)(0xb8000+160*line)+ 15*2); 84 | break; 85 | case REGULAR_FILE: 86 | s32_print("reg file", (u8*)(0xb8000+160*line)+ 15*2); 87 | break; 88 | } 89 | ++line; 90 | } 91 | 92 | next_offset = get_next_16_boundary(next_offset + fn_len); 93 | //clear_line(line); 94 | //s32_print_int(next_offset, (u8*)(0xb8000+160*line), 16); 95 | //return next_offset; 96 | *offset = (be32tole32(rom_fs_header->u.header8.nextfh) & 0xfffffff0); 97 | return rom_fs_header; 98 | } 99 | 100 | //INode return_inode; // because not yet malloc function, use global variable for return. 101 | 102 | INode *romfs_namei(SuperBlock *sb, char *dir) 103 | { 104 | u8 *buf = alloc_mem(); 105 | u32 read_count; 106 | u32 all_read_count=0; 107 | 108 | #if 1 109 | while(1) 110 | { 111 | //read_count = sb->device->dout(sb->device, buf, 0, sb->device->sector_size); 112 | read_count = sb->device->dout(sb->device, buf, 0, sb->device->storage_size); // read all ramdisk at once 113 | if (read_count == 0) return 0; // read nothing 114 | all_read_count += read_count; 115 | 116 | 117 | 118 | RomFsHeader *rom_fs_header; 119 | rom_fs_header = (RomFsHeader*)buf; 120 | u8 rom_fs_identify[9]=""; 121 | p_asm_memcpy(rom_fs_identify, rom_fs_header->u.id_str, 8); 122 | 123 | int line=0; 124 | #ifdef DEBUG_ROMFS 125 | clear_line(2); 126 | s32_print(rom_fs_identify, (u8*)(0xb8000+160*2)); 127 | line=3; 128 | clear_line(line); 129 | s32_print_int(rom_fs_header->size, (u8*)(0xb8000+160*line), 16); 130 | line=4; 131 | clear_line(line); 132 | 133 | s32_print_int(rom_fs_header->checksum, (u8*)(0xb8000+160*line), 16); 134 | #endif 135 | u32 volume_len = s_strlen(buf+16); 136 | 137 | #ifdef DEBUG_ROMFS 138 | line=5; 139 | clear_line(line); 140 | s32_print_int(volume_len, (u8*)(0xb8000+160*line), 10); 141 | line=6; 142 | clear_line(line); 143 | s32_print(buf+16, (u8*)(0xb8000+160*line)); 144 | #endif 145 | // get volume name, 16 byte alignment 146 | // romfs content: use get_next_16_boundary to get next 16 byte boundary. 147 | u32 next_offset = get_next_16_boundary(volume_len+0x10); 148 | line = 7; 149 | do 150 | { 151 | RomFsHeader *rom_fs_header; 152 | 153 | rom_fs_header = print_romfs_entry(line, &next_offset, buf, 0); 154 | rom_fs_header = (RomFsHeader*)(buf+next_offset); 155 | u32 fn_offset = next_offset +16; // file name offset, skip rom_fs_header 156 | u32 fn_len = s_strlen(buf+fn_offset); 157 | 158 | if (s_strcmp(buf+fn_offset, dir) == 0) 159 | { 160 | INode *return_inode = (INode*)alloc_mem(); 161 | clear_line(24); 162 | s32_print("find fn:", (u8*)(0xb8000+160*24)); 163 | s32_print(dir, (u8*)(0xb8000+160*24 + 13*2)); 164 | 165 | // fill inode 166 | return_inode->fn_name=buf+fn_offset; // fixed me: vary danger, because buf will to release or corrupt by other data. 167 | return_inode->dsize = be32tole32(rom_fs_header->size); 168 | return_inode->daddr = next_offset; 169 | return_inode->sb = sb; 170 | free_mem(buf); 171 | return return_inode; 172 | } 173 | 174 | u32 fn_content_offset = 0; 175 | u32 file_size = be32tole32(rom_fs_header->size); 176 | if (file_size) 177 | fn_content_offset = get_next_16_boundary(fn_offset+file_size); 178 | #if 0 179 | clear_line(line); 180 | s32_print("file size:", (u8*)(0xb8000+160*line)); 181 | s32_print_int(file_size, (u8*)(0xb8000+160*line+12*2), 16); 182 | ++line; 183 | #endif 184 | clear_line(line); 185 | s32_print("next_offset:", (u8*)(0xb8000+160*line)); 186 | s32_print_int(next_offset, (u8*)(0xb8000+160*line+12*2), 16); 187 | ++line; 188 | if (next_offset!=0 && fn_content_offset != 0) 189 | { 190 | clear_line(line); 191 | s32_print("fn_con_off:", (u8*)(0xb8000+160*line)); 192 | s32_print_int(fn_content_offset, (u8*)(0xb8000+160*line+12*2), 16); 193 | ++line; 194 | clear_line(0); 195 | clear_line(1); 196 | p_dump_u8(buf+fn_content_offset, file_size); 197 | //dump_u8(buf+fn_content_offset, 7); 198 | } 199 | }while(next_offset); 200 | 201 | line = 25; 202 | clear_line(line); 203 | s32_print("scan romfs ok", (u8*)(0xb8000+160*line)); 204 | #endif 205 | 206 | if (all_read_count >= sb->device->storage_size) 207 | return 0; 208 | } // end while(1) 209 | } 210 | 211 | u32 romfs_get_daddr(INode *inode) 212 | { 213 | u32 fn_len = 2;//s_strlen(inode->fn_name); 214 | u32 fn_content_offset = 0; 215 | u32 file_size = inode->dsize; 216 | if (file_size) 217 | fn_content_offset = get_next_16_boundary(inode->daddr + fn_len); 218 | return (fn_content_offset+16); 219 | } 220 | 221 | char * k_readdir(const char *dirname) 222 | { 223 | SuperBlock *sb = fs_type[ROMFS]; 224 | static u8 buf[512]; 225 | 226 | if (sb->device->dout(sb->device, buf, 0, sb->device->sector_size) != 0) 227 | { 228 | return 0; // error 229 | } 230 | 231 | RomFsHeader *rom_fs_header; 232 | rom_fs_header = (RomFsHeader*)buf; 233 | u8 rom_fs_identify[9]=""; 234 | p_asm_memcpy(rom_fs_identify, rom_fs_header->u.id_str, 8); 235 | 236 | int line; 237 | #if 0 238 | clear_line(2); 239 | s32_print(rom_fs_identify, (u8*)(0xb8000+160*2)); 240 | line=3; 241 | clear_line(line); 242 | s32_print_int(rom_fs_header->size, (u8*)(0xb8000+160*line), 16); 243 | line=4; 244 | clear_line(line); 245 | 246 | s32_print_int(rom_fs_header->checksum, (u8*)(0xb8000+160*line), 16); 247 | #endif 248 | u32 volume_len = s_strlen(buf+16); 249 | #if 0 250 | 251 | line=5; 252 | clear_line(line); 253 | s32_print_int(volume_len, (u8*)(0xb8000+160*line), 10); 254 | line=6; 255 | clear_line(line); 256 | s32_print(buf+16, (u8*)(0xb8000+160*line)); 257 | #endif 258 | 259 | // get volume name, 16 byte alignment 260 | // romfs content: use get_next_16_boundary to get next 16 byte boundary. 261 | u32 next_offset = get_next_16_boundary(volume_len+0x10); 262 | line = 7; 263 | do 264 | { 265 | RomFsHeader *rom_fs_header; 266 | 267 | rom_fs_header = print_romfs_entry(line, &next_offset, buf, 0); 268 | rom_fs_header = (RomFsHeader*)(buf+next_offset); 269 | u32 fn_offset = next_offset +16; // file name offset, skip rom_fs_header 270 | u32 fn_len = s_strlen(buf+fn_offset); 271 | 272 | #ifdef DEBUG_ROMFS 273 | s32_print_str(buf+fn_offset); 274 | s32_print_str("\r\n"); 275 | #endif 276 | u32 fn_content_offset = 0; 277 | u32 file_size = be32tole32(rom_fs_header->size); 278 | if (file_size) 279 | fn_content_offset = get_next_16_boundary(fn_offset+file_size); 280 | #if 0 281 | clear_line(line); 282 | s32_print("file size:", (u8*)(0xb8000+160*line)); 283 | s32_print_int(file_size, (u8*)(0xb8000+160*line+12*2), 16); 284 | ++line; 285 | clear_line(line); 286 | s32_print("next_offset:", (u8*)(0xb8000+160*line)); 287 | s32_print_int(next_offset, (u8*)(0xb8000+160*line+12*2), 16); 288 | ++line; 289 | if (next_offset!=0 && fn_content_offset != 0) 290 | { 291 | clear_line(line); 292 | s32_print("fn_con_off:", (u8*)(0xb8000+160*line)); 293 | s32_print_int(fn_content_offset, (u8*)(0xb8000+160*line+12*2), 16); 294 | ++line; 295 | clear_line(0); 296 | clear_line(1); 297 | p_dump_u8(buf+fn_content_offset, file_size); 298 | //dump_u8(buf+fn_content_offset, 7); 299 | } 300 | #endif 301 | }while(next_offset); 302 | 303 | #if 0 304 | line = 25; 305 | clear_line(line); 306 | s32_print("scan romfs ok", (u8*)(0xb8000+160*line)); 307 | #endif 308 | } 309 | -------------------------------------------------------------------------------- /tty/keyboard.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | #include "irq.h" 3 | #include "vga.h" 4 | #include "draw_func.h" 5 | #include "k_stdio.h" 6 | #include "k_ctype.h" 7 | #include "keyboard.h" 8 | 9 | static KeyboardBuf kb_buf; 10 | static u8 capslock=0; 11 | static u8 shift_r=0; 12 | static u8 shift_l=0; 13 | static u8 alt_r=0; 14 | static u8 alt_l=0; 15 | 16 | #define TEXT_MODE 0 17 | #define VGA_320X200X256 1 18 | static int vga_mode; 19 | 20 | int init_keyboard(void) 21 | { 22 | int vga_mode = TEXT_MODE; 23 | 24 | void keyboard_handler(int irq); 25 | s32_print("init keyboard", (u8*)(0xb8000+160*23)); 26 | 27 | kb_buf.count = 0; 28 | kb_buf.head = kb_buf.tail = kb_buf.buf; 29 | 30 | put_irq_handler(KEYBOARD_IRQ, keyboard_handler); 31 | enable_irq(KEYBOARD_IRQ); 32 | return 0; 33 | } 34 | 35 | void keyboard_handler(int irq) 36 | { 37 | static int cur_pos=0; 38 | //clear_line(22); 39 | //s32_print("*", (u8*)(0xb8000+160*22)); 40 | 41 | u8 scan_code = io_in8(0x60); 42 | if (kb_buf.count < KB_NUM) 43 | { 44 | *(kb_buf.head) = scan_code; 45 | ++kb_buf.head; 46 | if (kb_buf.head == kb_buf.buf + KB_NUM) 47 | kb_buf.head = kb_buf.buf; 48 | ++kb_buf.count; 49 | } 50 | s32_print_int(scan_code, (u8*)(0xb8000+160*22 + cur_pos*2), 16); 51 | cur_pos+=3; 52 | //if (lookup_key(scan_code & 0x7f, 0) == 'g') 53 | //switch_vga_mode(); 54 | } 55 | 56 | u8 get_byte_from_kb_buf(void) 57 | { 58 | u8 scan_code; 59 | 60 | while(kb_buf.count <= 0); 61 | 62 | disable_int(); 63 | scan_code = *(kb_buf.tail); 64 | ++kb_buf.tail; 65 | if (kb_buf.tail == kb_buf.buf + KB_NUM) 66 | kb_buf.tail = kb_buf.buf; 67 | --kb_buf.count; 68 | enable_int(); 69 | 70 | 71 | return scan_code; 72 | } 73 | 74 | static int keymap[NR_SCAN_CODES*KEYMAP_COLS] = 75 | { 76 | 0, 0, 77 | KEY_ESC, KEY_ESC, 78 | '1', '!', 79 | '2', '@', 80 | '3', '#', 81 | '4', '$', 82 | '5', '%', 83 | '6', '^', 84 | '7', '&', 85 | '8', '*', 86 | '9', '(', 87 | '0', ')', 88 | '-', '_', 89 | '=', '+', 90 | KEY_BACKSPACE, KEY_BACKSPACE, 91 | KEY_TAB, KEY_TAB, 92 | 'q', 'Q', 93 | 'w', 'W', 94 | 'e', 'E', 95 | 'r', 'R', 96 | 't', 'T', 97 | 'y', 'Y', 98 | 'u', 'U', 99 | 'i', 'I', 100 | 'o', 'O', 101 | 'p', 'P', 102 | '[', '{', 103 | ']', '}', 104 | KEY_ENTER, KEY_ENTER, 105 | KEY_CTRL_L, KEY_CTRL_L, 106 | 'a', 'A', 107 | 's', 'S', 108 | 'd', 'D', 109 | 'f', 'F', 110 | 'g', 'G', 111 | 'h', 'H', 112 | 'j', 'J', 113 | 'k', 'K', 114 | 'l', 'L', 115 | ';', ':', 116 | '\'', '\"', 117 | '`', '~', 118 | KEY_SHIFT_L, KEY_SHIFT_L, 119 | '\\', '|', 120 | 'z', 'Z', 121 | 'x', 'X', 122 | 'c', 'C', 123 | 'v', 'V', 124 | 'b', 'B', 125 | 'n', 'N', 126 | 'm', 'M', 127 | ',', '<', 128 | '.', '>', 129 | '/', '?', 130 | KEY_SHIFT_R, KEY_SHIFT_R, 131 | '*', '*', 132 | KEY_ALT_L, KEY_ALT_L, 133 | ' ', ' ', 134 | KEY_CAPSLOCK, KEY_CAPSLOCK, 135 | KEY_F1, KEY_F1, 136 | KEY_F2, KEY_F2, 137 | KEY_F3, KEY_F3, 138 | KEY_F4, KEY_F4, 139 | KEY_F5, KEY_F5, 140 | KEY_F6, KEY_F6, 141 | KEY_F7, KEY_F7, 142 | KEY_F8, KEY_F8, 143 | KEY_F9, KEY_F9, 144 | KEY_F10, KEY_F10, 145 | KEY_NUMLOCK, KEY_NUMLOCK, 146 | KEY_SCROLL_LOCK, KEY_SCROLL_LOCK, 147 | KEY_HOME, KEY_HOME, 148 | /* 0x48 */ KEY_UP, KEY_UP, 149 | /* 0x49 - PgUp */ KEY_PAGE_UP, KEY_PAGE_UP, 150 | /* 0x4A - '-' */ KEY_MINUS, KEY_MINUS, 151 | /* 0x4B - Left */ KEY_LEFT, KEY_LEFT, 152 | /* 0x4C - MID */ KEY_MID, KEY_MID, 153 | /* 0x4D - Right */ KEY_RIGHT, KEY_RIGHT, 154 | /* 0x4E - '+' */ KEY_PLUS, KEY_PLUS, 155 | /* 0x4F - End */ KEY_END, KEY_END, 156 | /* 0x50 - Down */ KEY_DOWN, KEY_DOWN, 157 | KEY_PAGE_DOWN, KEY_PAGE_DOWN, 158 | KEY_INSERT, KEY_INSERT, 159 | KEY_DOT, KEY_DOT, 160 | 0, 0, 161 | 0, 0, 162 | 0, 0, 163 | KEY_F11, KEY_F11, 164 | KEY_F12, KEY_F12, 165 | 0, 0, 166 | 0, 0, 167 | 0, 0, 168 | 0, 0, 169 | 0, 0, 170 | 0, 0, 171 | 0, 0, 172 | 0, 0, 173 | 0, 0, 174 | 0, 0, 175 | 0, 0, 176 | 0, 0, 177 | 0, 0, 178 | 0, 0, 179 | 0, 0, 180 | 0, 0, 181 | 0, 0, 182 | 0, 0, 183 | /*0x6b*/0, 0, 184 | 0,0, 185 | 0,0, 186 | 0,0, 187 | 0,0, 188 | 0,0, 189 | 0,0, 190 | 0,0, 191 | 0,0, 192 | 0,0, 193 | 0,0, 194 | 0,0, 195 | 0,0, 196 | 0,0, 197 | 0,0, 198 | 0,0, 199 | 0,0, 200 | 0,0, 201 | 0,0, 202 | 0,0, 203 | /*0x7f*/0, 0 204 | }; 205 | 206 | int lookup_key(u8 scan_code, u8 col) 207 | { 208 | return keymap[scan_code*KEYMAP_COLS+col]; 209 | //return KEY_UP; 210 | } 211 | 212 | typedef struct Pair_ 213 | { 214 | s16 key1; 215 | s16 key2; 216 | }Pair; 217 | 218 | Pair shift_map[]= 219 | { 220 | '`', '~', 221 | '1', '!', 222 | '2', '@', 223 | '3', '#', 224 | '4', '$', 225 | '5', '%', 226 | '6', '^', 227 | '7', '&', 228 | '8', '*', 229 | '9', '(', 230 | '0', ')', 231 | '-', '_', 232 | '=', '+', 233 | '[', '{', 234 | ']', '}', 235 | '\\', '|', 236 | ';', ':', 237 | '\'', '\"', 238 | ',', '<', 239 | '.', '>', 240 | '/', '?' 241 | }; 242 | 243 | int to_shift_key(int key) 244 | { 245 | int map_key=key; 246 | 247 | if (('a' <= key) && (key <= 'z')) 248 | { 249 | 250 | if (capslock==0) 251 | { 252 | if (shift_r==1 || shift_l==1) 253 | map_key = toupper(key); 254 | else 255 | map_key = tolower(key); 256 | } 257 | else 258 | { 259 | if (shift_r==1 || shift_l==1) 260 | map_key = tolower(key); 261 | else 262 | map_key = toupper(key); 263 | } 264 | 265 | } 266 | else 267 | { 268 | } 269 | return map_key; 270 | } 271 | 272 | int parse_scan_code(KeyStatus *key_status, int keyborad_mode) 273 | { 274 | u8 make; 275 | int ret=0; 276 | static u8 keymap_col=0; 277 | 278 | if(kb_buf.count > 0) 279 | { 280 | u8 scan_code = get_byte_from_kb_buf(); 281 | switch (scan_code) 282 | { 283 | case 0xe1: 284 | break; 285 | case 0xe0: 286 | scan_code = get_byte_from_kb_buf(); 287 | key_status->key = lookup_key(scan_code & 0x7f, keymap_col); 288 | key_status->press = ((scan_code & 0x80) ? RELEASE: PRESS); 289 | break; 290 | default: 291 | if (keyborad_mode==ASCII_MODE && key_status->press == PRESS) 292 | { 293 | switch (key_status->key) 294 | { 295 | case KEY_SHIFT_R: 296 | shift_r=1; 297 | break; 298 | case KEY_SHIFT_L: 299 | shift_l=1; 300 | break; 301 | } 302 | } 303 | if (keyborad_mode==ASCII_MODE && key_status->press == RELEASE) 304 | { 305 | switch (key_status->key) 306 | { 307 | case KEY_SHIFT_R: 308 | shift_r=0; 309 | break; 310 | case KEY_SHIFT_L: 311 | shift_l=0; 312 | break; 313 | case KEY_CAPSLOCK: 314 | capslock = (!capslock); 315 | break; 316 | } 317 | } 318 | 319 | 320 | //key_status->key = to_shift_key(key_status->key); 321 | 322 | if (capslock==0) 323 | { 324 | if (shift_r==1 || shift_l==1) 325 | keymap_col = 1; 326 | else 327 | keymap_col = 0; 328 | } 329 | else 330 | { 331 | if (shift_r==1 || shift_l==1) 332 | keymap_col = 0; 333 | else 334 | keymap_col = 1; 335 | } 336 | key_status->key = lookup_key(scan_code & 0x7f, keymap_col); 337 | key_status->press = ((scan_code & 0x80) ? RELEASE: PRESS); 338 | break; 339 | } 340 | 341 | } 342 | else 343 | { 344 | ret=1; 345 | } 346 | 347 | return ret; 348 | } 349 | 350 | 351 | int switch_mode(int mode) 352 | { 353 | int set_vga_mode(void); // system call 354 | void set_03_mode(void); 355 | 356 | switch (mode) 357 | { 358 | case TEXT_MODE: 359 | { 360 | if (vga_mode != TEXT_MODE) 361 | { 362 | set_03_mode(); 363 | vga_mode = TEXT_MODE; 364 | 365 | for (int i=0 ; i < CONSOLE_NUM - 1; ++i) 366 | { 367 | Console *console = &console_table[i]; 368 | clear_console(console); 369 | } 370 | 371 | } 372 | break; 373 | } 374 | case VGA_320X200X256: 375 | { 376 | if (vga_mode != VGA_320X200X256) 377 | { 378 | set_vga_mode(); // system call 379 | vga_mode = VGA_320X200X256; 380 | } 381 | break; 382 | } 383 | } 384 | 385 | } 386 | 387 | int keyboard_read(Tty *tty) 388 | { 389 | u8 make; 390 | int ret=0; 391 | static u8 keymap_col=0; 392 | static u8 alt_l=0; 393 | 394 | KeyStatus key_status; 395 | if(kb_buf.count > 0) 396 | { 397 | u8 scan_code = get_byte_from_kb_buf(); 398 | //put_key(tty, get_byte_from_kb_buf() ); 399 | key_status.key = lookup_key(scan_code & 0x7f, keymap_col); 400 | key_status.press = ((scan_code & 0x80) ? RELEASE: PRESS); 401 | // alt+F1, alt+F2, alt+F3 switch tty 402 | // else pass to tty inbuf 403 | switch (key_status.key) 404 | { 405 | case KEY_F1: 406 | case KEY_F2: 407 | case KEY_F3: 408 | if (alt_l == 1 && key_status.press == PRESS) 409 | { 410 | switch_mode(TEXT_MODE); 411 | //set_cursor(0); 412 | 413 | select_tty(key_status.key - KEY_F1); 414 | } 415 | alt_l = 0; 416 | break; 417 | case KEY_F6: 418 | if (alt_l == 1 && key_status.press == PRESS) 419 | { 420 | select_tty(3); 421 | switch_mode(VGA_320X200X256); 422 | 423 | draw_256_grid(); 424 | //draw_box(); 425 | extern u8 bg_raw_data[]; 426 | extern int bg_w; 427 | extern int bg_h; 428 | extern u8 palette_data[]; 429 | 430 | extern u8 os_bg_raw_data[]; 431 | extern int os_bg_w; 432 | extern int os_bg_h; 433 | extern u8 os_palette_data[]; 434 | 435 | draw_bg(0, 0, os_bg_raw_data, os_bg_w, os_bg_h, os_palette_data); 436 | //draw_bg(0, 0, bg_raw_data, bg_w, bg_h, palette_data); 437 | draw_str(20, 100, 15); 438 | #if 0 439 | draw_box_1(40, 0, 3); 440 | draw_box_1(40, 0, 3); 441 | draw_box_1(40, 50, 5); 442 | draw_box_1(100, 100, 10); 443 | #endif 444 | } 445 | alt_l = 0; 446 | break; 447 | case KEY_ALT_L: 448 | alt_l = 1; 449 | break; 450 | case 0x20 ... 0x7e: // ascii printable char. gnu extension: I don't want use gnu extension, but it is very convenience. 451 | if (key_status.press == PRESS) 452 | put_key(tty, key_status.key); 453 | alt_l = 0; 454 | break; 455 | default: 456 | if (key_status.press == PRESS) 457 | put_key(tty, key_status.key); 458 | alt_l = 0; 459 | break; 460 | 461 | } 462 | } 463 | 464 | } 465 | -------------------------------------------------------------------------------- /c-bootloader/fat.c: -------------------------------------------------------------------------------- 1 | // read fat floppy disk 2 | 3 | //#define DOS_COM 4 | #define NOCLIB 5 | 6 | #ifndef NOCLIB 7 | #include 8 | #include 9 | #endif 10 | 11 | #define __NOINLINE __attribute__((noinline)) 12 | #define __REGPARM __attribute__ ((regparm(3))) 13 | #define __PACKED __attribute__((packed)) 14 | #define __NORETURN __attribute__((noreturn)) 15 | 16 | #define IMAGE_SIZE 8192 17 | #define BLOCK_SIZE 512 18 | #define IMAGE_LMA (0x2000) 19 | //#define IMAGE_LMA 0x8000 20 | #define IMAGE_ENTRY 0x800c 21 | #define buf_addr_val (*(u8 volatile*(IMAGE_LMA))) 22 | 23 | 24 | /* XXX these must be at top */ 25 | #include "code16gcc.h" 26 | #ifdef DOS_COM 27 | __asm__ ("jmp main\n"); 28 | #else 29 | __asm__ ("jmp main\n"); 30 | //__asm__ ("jmpl $0, $main\n"); 31 | #endif 32 | 33 | // copy from write_os/src/chapter2/2/boot.S 34 | __asm__ ("BS_OEMName: .ascii \"descent \" \n"); /* OEM String, 8 bytes required */ 35 | __asm__ ("BPB_BytsPerSec: .2byte 512 \n"); /* Bytes per sector */ 36 | __asm__ ("BPB_SecPerCluster: .byte 1 \n"); /* Sector per cluster */ 37 | __asm__ ("BPB_ResvdSecCnt: .2byte 1 \n"); /* Reserved sector count */ 38 | __asm__ ("BPB_NumFATs: .byte 2 \n"); /* Number of FATs */ 39 | __asm__ ("BPB_RootEntCnt: .2byte 224 \n"); /* Root entries count */ 40 | __asm__ ("BPB_TotSec16: .2byte 2880 \n"); /* Total sector number */ 41 | __asm__ ("BPB_Media: .byte 0xf0 \n"); /* Media descriptor */ 42 | __asm__ ("BPB_FATSz16: .2byte 9 \n"); /* FAT size(sectors) */ 43 | __asm__ ("BPB_SecPerTrk: .2byte 18 \n"); /* Sector per track */ 44 | __asm__ ("BPB_NumHeads: .2byte 2 \n"); /* Number of magnetic heads */ 45 | __asm__ ("BPB_HiddSec: .4byte 0 \n"); /* Number of hidden sectors */ 46 | __asm__ ("BPB_TotSec32: .4byte 0 \n"); /* If TotSec16 equal 0, this works */ 47 | __asm__ ("BS_DrvNum: .byte 0 \n"); /* Driver number of interrupt 13 */ 48 | __asm__ ("BS_Reserved1: .byte 0 \n"); /* Reserved */ 49 | __asm__ ("BS_BootSig: .byte 0x29 \n"); /* Boot signal */ 50 | __asm__ ("BS_VolID: .4byte 0 \n"); /* Volume ID */ 51 | __asm__ ("BS_VolLab: .ascii \"c-loader0.1\"\n"); /* Volume label, 11 bytes required */ 52 | __asm__ ("BS_FileSysType: .ascii \"FAT12 \" \n"); /* File system type, 8 bytes required */ 53 | 54 | //#define byte_per_sector 512 55 | 56 | typedef unsigned char u8; 57 | typedef unsigned short u16; 58 | typedef unsigned int u32; 59 | 60 | u8 ln[] = "LOADER BIN"; 61 | 62 | char* itoa(int n, u8* str, int radix); 63 | //void __NOINLINE __REGPARM print(const char *s); 64 | /* BIOS interrupts must be done with inline assembly */ 65 | void __NOINLINE __REGPARM print(const char *s){ 66 | while(*s){ 67 | __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)); 68 | s++; 69 | } 70 | } 71 | 72 | #ifdef DOS_COM 73 | void print_num(int n, u8 *sy) 74 | { 75 | u8 str[10]; 76 | u8 *s = str; 77 | s = itoa(n, s, 10); 78 | //print("\r\n"); 79 | print(sy); 80 | print(":"); 81 | print(s); 82 | } 83 | #endif 84 | 85 | #ifdef DOS_COM 86 | void dump_u8(u8 *buff, u16 count) 87 | { 88 | void h2c(u8 hex, u8 ch[2]); 89 | 90 | for (int i=0 ; i < count ; ++i) 91 | { 92 | if (i%16==0) 93 | print("\r\n"); 94 | u8 c[4]=""; 95 | u8 h=*(buff+i); 96 | c[3]=0; 97 | c[2]=0x20; 98 | h2c(h, c); 99 | print(c); 100 | } 101 | } 102 | #endif 103 | 104 | 105 | 106 | #ifdef DOS_COM 107 | char* itoa(int n, u8* str, int radix) 108 | { 109 | char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 110 | char* p=str; 111 | char* head=str; 112 | 113 | if(!p || radix < 2 || radix > 36) 114 | return p; 115 | if (n==0) 116 | { 117 | *p++='0'; 118 | *p=0; 119 | return str; 120 | } 121 | if (radix == 10 && n < 0) 122 | { 123 | *p++='-'; 124 | n= -n; 125 | } 126 | while(n) 127 | { 128 | *p++=digit[n%radix]; 129 | n/=radix; 130 | } 131 | *p=0; 132 | for (--p; head < p ; ++head, --p) 133 | { 134 | char temp=*head; 135 | *head=*p; 136 | *p=temp; 137 | } 138 | return str; 139 | } 140 | 141 | void h2c(u8 hex, u8 ch[2]) 142 | { 143 | u8 l = hex >> 4; 144 | 145 | if ( 0<= l && l <= 9) 146 | { 147 | ch[0]=l+0x30; 148 | } 149 | else 150 | { 151 | ch[0]=l+0x41-0xa; //a 152 | ch[0]=l+0x61-0xa; // A 153 | } 154 | 155 | l = hex & 0x0f; 156 | 157 | if ( 0<= l && l <= 9) 158 | { 159 | ch[1]=l+0x30; 160 | } 161 | else 162 | { 163 | ch[1]=l+0x41-0xa; //a 164 | ch[1]=l+0x61-0xa; // A 165 | } 166 | } 167 | #endif 168 | 169 | //ref: http://forum.osdev.org/viewtopic.php?f=1&t=7762 170 | // read a sector 171 | // 1.44 MB floppy 172 | // HeadNumber: 0, 1 173 | // CylNum: 0 - 79 174 | // sector number: 1 - 18 175 | #if 0 176 | // directory assign value in inline assembly 177 | __asm__ __volatile__("movb $0, %ch\n"); 178 | __asm__ __volatile__("movb $2, %cl\n"); // set the sector number, bits 0-5 179 | __asm__ __volatile__("movb $0, %dh\n"); 180 | __asm__ __volatile__("movb $0, %dl\n"); // disk no, 0 -> A disk 181 | #endif 182 | 183 | int __REGPARM read_sector(u8 *buff, u8 sector_no, u8 track_no, u8 head_no) 184 | { 185 | #if 0 186 | sector_no=3; // cl 187 | track_no=0; // ch 188 | head_no=0; // dh 189 | disk_no=0; // dl 190 | #endif 191 | 192 | __asm__ __volatile__("movb $2, %ah\n"); 193 | __asm__ __volatile__("movb $1, %al\n"); 194 | #if 1 195 | __asm__ ("int $0x13\n" 196 | : 197 | :"b"(buff), "c"(track_no << 8 | sector_no), "d"(head_no << 8) 198 | ); 199 | #endif 200 | return 0; 201 | } 202 | 203 | #if 0 204 | int s_strncmp(const char *s1, const char *s2, u32 n); 205 | { 206 | char *p1 = s1; 207 | char *p2 = s2; 208 | 209 | while (*p1 == *p2) 210 | ++p1; 211 | ++p2 212 | 213 | } 214 | #endif 215 | 216 | #ifdef DOS_COM 217 | int main(void) 218 | #else 219 | void __NORETURN main(void) 220 | #endif 221 | { 222 | __asm__ ("mov %cs, %ax\n"); 223 | __asm__ ("mov %ax, %ds\n"); 224 | /* 225 | __asm__ ("mov $0x07a0, %ax\n"); 226 | __asm__ ("mov %ax, %ss\n"); 227 | __asm__ ("mov $0, %esp\n"); 228 | print("woo hoo!\r\n:)"); 229 | */ 230 | //void h2c(u8 hex, u8 ch[2]) 231 | 232 | 233 | #if 1 234 | 235 | //ref: http://forum.osdev.org/viewtopic.php?f=1&t=7762 236 | u8 sector_no = 1; // cl, 1 - 18 237 | u8 track_no=0; // ch 238 | u8 head_no=0; // dh 239 | 240 | u16 byte_per_sector = 512; 241 | u16 root_entry_count = 0; 242 | u8 *buff = (u8*)IMAGE_LMA; 243 | 244 | //#ifdef DOS_COM 245 | #if 1 246 | //int r = read_sector(buff, sector_no, 0, 0, 0); 247 | 248 | #if 0 249 | // logic sector no 19 is root directory 250 | sector_no = 1; // cl, 1 - 18 251 | track_no=0; // ch 252 | head_no=0; // dh 253 | disk_no=0; // dl 254 | #endif 255 | 256 | int r = read_sector(buff, sector_no, track_no, head_no); 257 | byte_per_sector = ((buff[12] << 8) | buff[11]); 258 | //byte_per_sector = 512; 259 | //root_entry_count = ((buff[18] << 8) | buff[17]); 260 | root_entry_count = 224; 261 | 262 | #ifdef DOS_COM 263 | print_num(byte_per_sector, "byte_per_sector"); 264 | print_num(root_entry_count, "root_entry_count"); 265 | #endif 266 | 267 | u16 root_dir_secotrs = 0; 268 | if (root_entry_count * 32 % byte_per_sector != 0) 269 | root_dir_secotrs = (root_entry_count * 32 / byte_per_sector) + 1; 270 | else 271 | root_dir_secotrs = (root_entry_count * 32 / byte_per_sector); 272 | 273 | #ifdef DOS_COM 274 | print_num(root_dir_secotrs, "root_dir_secotrs"); // root dir occupy how many sectors 275 | #endif 276 | 277 | 278 | //int root_sec_no = 21; 279 | 280 | 281 | u16 root_sec_no = 19; 282 | u16 read_sec = 0; 283 | 284 | //for (int i=0 ; i < 1 ; ++i, ++cur_sec_no) 285 | //for (int i=0 ; i <= root_dir_secotrs ; ++i, ++cur_sec_no) 286 | for (int i=root_sec_no ; i <= root_dir_secotrs+root_sec_no ; ++i) 287 | { 288 | #ifdef DOS_COM 289 | print("\r\n"); 290 | print_num(i, "cur sec no"); // root dir occupy how many sectors 291 | #endif 292 | track_no = (((i)/18) >> 1); 293 | head_no = (((i)/18) & 1); 294 | sector_no = (((i)%18) + 1); 295 | r = read_sector(buff, sector_no, track_no, head_no); 296 | 297 | //for (u16 j=0 ; j < 2 ; ++j) 298 | //for (u16 j=0 ; j < 16 ; ++j) 299 | for (u16 j=0 ; j < 512/32 ; ++j) 300 | { 301 | u16 f_c = ((buff[0x1b+j*32] << 8) | buff[0x1a+j*32]); // first cluster 302 | #ifdef DOS_COM 303 | u32 file_size = (( buff[0x1f + (j*32)] << 24) | (buff[0x1e + (j*32)] << 16) | (buff[0x1d + (j*32)] << 8) | buff[0x1c + (j*32)]); 304 | #endif 305 | //u32 file_size = 0; 306 | //u32 file_size = ( buff[0x1f+(j*32)] << 24); 307 | 308 | u8 *filename; 309 | #if 0 310 | for (int i=0 ; i < 11 ; ++i) 311 | filename[i] = buff[i+(j*32)]; 312 | #endif 313 | filename = buff + (j*32); 314 | 315 | #if 1 316 | #ifdef DOS_COM 317 | if (filename[0] == 0xe5) // del file 318 | continue; 319 | #endif 320 | #ifdef DOS_COM 321 | if (filename[0] == 0) 322 | { 323 | print("\r\nsearch end\r\n"); 324 | goto search_end; 325 | } 326 | #endif 327 | #endif 328 | 329 | 330 | #ifdef DOS_COM 331 | u8 attr = buff[0x0b + (j*32)]; 332 | #endif 333 | 334 | r = 0; 335 | u8 *p = ln; 336 | for (int i=0 ; i < 11 ; ++i) 337 | { 338 | if (*filename++ != *p++) 339 | { 340 | r = 0; 341 | break; 342 | } 343 | r = 1; 344 | 345 | } 346 | 347 | if (r) 348 | { 349 | read_sec = f_c - 2 + root_dir_secotrs + 19; 350 | #ifdef DOS_COM 351 | print("\r\n"); 352 | print("load it\r\n"); 353 | print("\r\n"); 354 | if (((attr >> 3) & 1) == 1) // label 355 | { 356 | print("label:"); 357 | print(filename); 358 | continue; 359 | } 360 | else 361 | { 362 | print("\r\n"); 363 | print(filename); 364 | print_num(f_c, " f_c"); 365 | print_num(file_size, " file_size"); 366 | print("\r\n"); 367 | } 368 | #endif 369 | goto search_end; 370 | } 371 | 372 | 373 | 374 | } 375 | 376 | 377 | } 378 | 379 | search_end: 380 | if (read_sec != 0) 381 | { 382 | #ifdef DOS_COM 383 | print_num(read_sec, "read_sec"); 384 | #endif 385 | track_no = ((read_sec/18) >> 1); 386 | head_no = ((read_sec/18) & 1); 387 | sector_no = ((read_sec%18) + 1); 388 | #if 0 389 | print_num(track_no, "track_no"); 390 | print_num(head_no, "head_no"); 391 | #endif 392 | // if no the line, buff will get wrong data, very strange. 393 | print('s'); 394 | r = read_sector(buff, sector_no, track_no, head_no); 395 | 396 | #ifdef DOS_COM 397 | for (int i=0 ; i < 32 ; ++i) 398 | { 399 | if (i%16==0) 400 | print("\r\n"); 401 | u8 c[4]=""; 402 | u8 h=*(buff+i); 403 | c[3]=0; 404 | c[2]=0x20; 405 | h2c(h, c); 406 | print(c); 407 | } 408 | #endif 409 | //void* e = (void*)IMAGE_ENTRY; 410 | void* e = buff; 411 | //__asm__ __volatile__("" : : "d"(bios_drive)); 412 | goto *e; 413 | } 414 | 415 | 416 | #if 0 417 | for (int i=0 ; i < 32 ; ++i) 418 | { 419 | if (i%16==0) 420 | print("\r\n"); 421 | u8 c[4]=""; 422 | u8 h=*(buff+i); 423 | c[3]=0; 424 | c[2]=0x20; 425 | h2c(h, c); 426 | print(c); 427 | } 428 | #endif 429 | 430 | #endif 431 | 432 | #if 0 433 | //if (argc >= 2) 434 | { 435 | //sector_no = argv[1] - 0x30 ; // cl, 1 - 18 436 | } 437 | print("\r\nsector:\r\n"); 438 | print(argv[1][0]); 439 | sector_no = argv[1] - 0x30 ; // cl, 1 - 18 440 | #endif 441 | 442 | #if 0 443 | for (int i=1 ; i <= 5 ; ++i) 444 | { 445 | sector_no = i; 446 | int r = read_sector(buff, sector_no, 0, 0, 0); 447 | 448 | for (int i=0 ; i < 32 ; ++i) 449 | { 450 | if (i%16==0) 451 | print("\r\n"); 452 | u8 c[4]=""; 453 | u8 h=*(buff+i); 454 | c[3]=0; 455 | c[2]=0x20; 456 | h2c(h, c); 457 | print(c); 458 | } 459 | } 460 | #ifndef DOS_COM 461 | while(1); 462 | #endif 463 | #endif 464 | 465 | 466 | #endif 467 | 468 | 469 | #ifdef DOS_COM 470 | // 回到 DOS 471 | __asm__ ("mov $0x4c00, %ax\n"); 472 | __asm__ ("int $0x21\n"); 473 | #else 474 | while(1); 475 | #endif 476 | } 477 | -------------------------------------------------------------------------------- /kernel_loader/kloader_init.S: -------------------------------------------------------------------------------- 1 | /* 2 | * the kernel loader will initialize c runtime and enter x86 protected mode 3 | */ 4 | 5 | #include "pm.h" 6 | #include "common.h" 7 | .equ copy_elf_code_addr, (copy_elf_code+(0x9000*16)) 8 | .equ enter_pm_addr, (enter_pm+(0x9000*16)) 9 | .equ enter_pm1_addr, (enter_pm1+(0x9000*16)) 10 | .equ p_vb_addr, (p_vb+(0x9000*16)) 11 | 12 | #define BIG_REAL_MODE 13 | 14 | .data 15 | vb: .int 0xb8000 16 | count: .int 16 17 | #vb: .int 0x100000 18 | LABEL_GDT: Descriptor 0, 0, 0 # empty descriptor 19 | LABEL_DESC_FLAT_C: Descriptor 0, 0xfffff, DA_CR | DA_32 | DA_LIMIT_4K 20 | LABEL_DESC_FLAT_RW: Descriptor 0, 0xfffff, DA_DRW | DA_32 | DA_LIMIT_4K 21 | LABEL_DESC_VIDEO: Descriptor 0xb8000, 0xffff, DA_DRW | DA_DPL3 22 | LABEL_DESC_4G_X: Descriptor 0, 0xfffff, DA_CR | DA_32 | DA_LIMIT_4K 23 | LABEL_DESC_4G_RW: Descriptor 0, 0xfffff, DA_DRW | DA_32 | DA_LIMIT_4K 24 | LABEL_DESC_NORMAL: Descriptor 0, 0xffff, DA_DRW # Normal descriptor is for back to real mode. 25 | LABEL_DESC_CODE16: Descriptor 0, 0xffff, DA_C # 非一致程式碼段, 16 26 | 27 | .set gdt_len, (. - LABEL_GDT) 28 | gdt_ptr: .2byte (gdt_len - 1) 29 | .4byte loader_base_phy_addr+LABEL_GDT 30 | 31 | .set sel_normal, (LABEL_DESC_NORMAL - LABEL_GDT) 32 | .set sel_code16, (LABEL_DESC_CODE16 - LABEL_GDT) 33 | .set sel_flat_c, (LABEL_DESC_FLAT_C - LABEL_GDT) 34 | .set sel_flat_rw, (LABEL_DESC_FLAT_RW - LABEL_GDT) 35 | .set sel_video, (LABEL_DESC_VIDEO - LABEL_GDT + SA_RPL3) 36 | #.set sel_video, (LABEL_DESC_VIDEO - LABEL_GDT) 37 | .set select_4g_x, (LABEL_DESC_4G_X - LABEL_GDT) 38 | .set select_4g_rw, (LABEL_DESC_4G_RW - LABEL_GDT) 39 | 40 | LABEL_STACK: 41 | .space 1024, 0 42 | .set top_of_stack, (. - LABEL_STACK) 43 | 44 | .set pm_phy_addr, (loader_base_phy_addr+LABEL_PM_START) 45 | 46 | 47 | .code16 48 | .extern __bss_start__ 49 | .extern __bss_end__ 50 | 51 | .text 52 | .global _start 53 | _start: 54 | mov %cs, %ax 55 | #mov $0xa00, %ax 56 | mov %ax, %ds 57 | mov %ax, %es 58 | #movw $0x0, %ax 59 | #movw %ax, %ds 60 | mov %ax, %ss 61 | # setup stack 62 | mov $0xfff0, %sp # why not setting 0xffff to %sp, in ms dos, 0xfff0 is ok, 0xffb will get core dump 63 | 64 | #ifdef BIG_REAL_MODE 65 | movw %ax, (LABEL_GO_BACK_TO_REAL+3) # modify segment value, indexed memory mode, ref professional aeesmbly language p 102. 66 | 67 | /* Initialize 16-bits code segment descriptor. */ 68 | xor %eax, %eax 69 | mov %cs, %ax 70 | shl $4, %eax 71 | addl $(LABEL_SEG_CODE16), %eax 72 | movw %ax, (LABEL_DESC_CODE16 + 2) 73 | shr $16, %eax 74 | movb %al, (LABEL_DESC_CODE16 + 4) 75 | movb %ah, (LABEL_DESC_CODE16 + 7) 76 | 77 | 78 | lgdt gdt_ptr 79 | 80 | cli 81 | 82 | # open a20 line 83 | inb $0x92, %al 84 | orb $0b00000010, %al 85 | outb %al, $0x92 86 | 87 | # enable protect mode 88 | movl %cr0, %eax 89 | orl $1, %eax 90 | movl %eax, %cr0 91 | 92 | #xchg %bx, %bx 93 | #ljmpl $sel_flat_c, $pm_phy_addr 94 | ljmpl $sel_flat_c, $enter_pm1_addr 95 | 96 | #endif 97 | big_real_mode: 98 | #xchg %bx, %bx 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | # call disp_str 108 | call init_bss_asm 109 | # for bss 110 | # movw $0x0, %ax 111 | # movw %ax, %ds 112 | # call p 113 | call start_c 114 | # call text_test 115 | # call disp_str2 116 | jmp . 117 | #disp_str: 118 | # mov $BootMessage, %ax 119 | # mov %ax,%bp 120 | # mov $16,%cx 121 | # mov $0x1301,%ax 122 | # mov $0x00c,%bx 123 | # mov $0,%dl 124 | # int $0x10 125 | # ret 126 | #BootMessage:.ascii "Hello, c-env world!" 127 | #disp_str2: 128 | # mov $str2, %ax 129 | # mov %ax,%bp 130 | # mov $5,%cx 131 | # mov $0x1301,%ax 132 | # mov $0x00c,%bx 133 | # mov $0,%dl 134 | # int $0x10 135 | # ret 136 | #str2:.ascii "after" 137 | 138 | 139 | #if 0 140 | __asm__ __volatile__ 141 | ( 142 | "movw $0, %0\n" 143 | "int $0x13\n" 144 | "setcb %0" 145 | :"=m"(failed), "=a"(num_blocks_transferred) 146 | :"a"(0x0200|blocks), "b"(buff), "c"(track_no << 8 | sector_no), "d"(head_no << 8 | disk_no) 147 | ); 148 | #endif 149 | 150 | .globl asm_read_sector 151 | asm_read_sector: 152 | pushl %ebp 153 | mov %esp, %ebp 154 | 155 | mov 28(%ebp), %ax 156 | mov 8(%ebp), %bx 157 | int $0x13 158 | 159 | mov %ebp, %esp 160 | pop %ebp 161 | ret 162 | 163 | # use big real mode copy to 4g range 164 | # use %fs for segment register, %fs points to 4g memory space 165 | .globl asm_4g_memcpy 166 | # ex: 167 | # asm_absolute_memcpy((u8*)0x100, (u8 *)IMAGE_LMA, 512*3); 168 | # copy IMAGE_LMA to 0x100 169 | asm_4g_memcpy: 170 | pushl %ebp 171 | mov %esp, %ebp 172 | 173 | pushl %esi 174 | pushl %edi 175 | pushl %ecx 176 | 177 | mov 8(%ebp), %edi /* Destination */ 178 | mov 12(%ebp), %esi /* Source */ 179 | mov 16(%ebp), %ecx /* Counter */ 180 | 1: 181 | cmp $0, %ecx /* Loop counter */ 182 | jz 2f 183 | movb %ds:(%esi), %al 184 | inc %esi 185 | movb %al, %fs:(%edi) 186 | 187 | movb %fs:(%edi), %al 188 | 189 | # cmpl $0, count 190 | # jz 3f 191 | #xchg %bx, %bx 192 | # call disp_al 193 | # addl $2, vb 194 | 195 | # bios call: wait key 196 | # xor %eax,%eax 197 | # int $0x16 198 | 199 | decl count 200 | 3: 201 | inc %edi 202 | dec %ecx 203 | jmp 1b 204 | 2: 205 | mov 8(%ebp), %eax 206 | pop %ecx 207 | pop %edi 208 | pop %esi 209 | mov %ebp, %esp 210 | pop %ebp 211 | retl 212 | 213 | .global disp_ax 214 | disp_ax: 215 | xchg %bx, %bx 216 | push %bx 217 | mov %ax, %bx 218 | shr $4, %al 219 | call disp_al 220 | mov %bx, %ax 221 | call disp_al 222 | add $2, vb 223 | pop %bx 224 | ret 225 | 226 | .global disp_al 227 | disp_al: 228 | pushl %ecx 229 | pushl %edx 230 | pushl %esi 231 | mov vb, %esi 232 | 233 | movb $0x09, %ah # 0000: 黑底 1010: 綠色字 234 | movb %al, %dl 235 | shr $4, %al 236 | movl $2, %ecx 237 | .begin: 238 | andb $0x0f, %al 239 | cmp $9, %al 240 | ja .3 # cf=0, zf=0, above 9 (>9) 241 | #addb $'0', %al 242 | addb $0x30, %al 243 | jmp .4 244 | .3: 245 | sub $0x0A, %al 246 | #add $'A', %al 247 | add $0x41, %al 248 | .4: 249 | #mov [gs:edi], ax 250 | mov %ax, %fs:(%esi) 251 | addl $2, vb 252 | mov vb, %esi 253 | 254 | 255 | mov %dl, %al 256 | loop .begin 257 | 258 | popl %esi 259 | popl %edx 260 | popl %ecx 261 | 262 | ret 263 | 264 | 265 | .globl write_mem8 266 | write_mem8: 267 | pushl %ebp 268 | mov %esp, %ebp 269 | #movw $0xa000, %ax # graphic mode 270 | movw $0xb800, %ax # text mode 271 | movw %ax, %gs 272 | movl 8(%ebp), %ecx; 273 | # mov $0x0, %ecx; 274 | movb 12(%ebp), %al; 275 | movb %al, %gs:(%ecx) 276 | #movb $'A', %gs:(%ecx) 277 | popl %ebp 278 | ret 279 | 280 | 281 | # init bss 282 | init_bss_asm: 283 | movw $__bss_end__, %di /* Destination */ 284 | movw $__bss_start__, %si /* Source */ 285 | # movw $0x0, %ax 286 | # movw %ax, %gs 287 | jmp 2f 288 | 1: 289 | mov $0, %eax 290 | movw %si, %ax 291 | movb $0x1, (%eax) 292 | # movb $0x1, %ds:(%eax) 293 | add $1, %si 294 | 295 | 2: 296 | cmpw %di, %si 297 | jne 1b 298 | ret 299 | 300 | # can specify segment register 301 | .globl asm_seg_memcpy 302 | asm_seg_memcpy: 303 | pushl %ebp 304 | mov %esp, %ebp 305 | 306 | pushl %esi 307 | pushl %edi 308 | pushl %ecx 309 | 310 | 311 | mov 8(%ebp), %edi /* Destination */ 312 | mov 12(%ebp), %esi /* Source */ 313 | mov 16(%ebp), %ecx /* Counter */ 314 | mov 20(%ebp), %ax /* %fs value type: u16 */ 315 | mov %ax, %fs # setting %fs 316 | MemCpy.11: 317 | cmp $0, %ecx /* Loop counter */ 318 | jz MemCpy.22 319 | movb %ds:(%esi), %al 320 | inc %esi 321 | movb %al, %fs:(%edi) 322 | inc %edi 323 | dec %ecx 324 | jmp MemCpy.11 325 | MemCpy.22: 326 | mov 8(%ebp), %eax 327 | pop %ecx 328 | pop %edi 329 | pop %esi 330 | mov %ebp, %esp 331 | pop %ebp 332 | ret 333 | 334 | # copy from: write_os/src/chapter3/8/lib.h 335 | # ex: 336 | # asm_memcpy((u8*)0x100, (u8 *)IMAGE_LMA, 512*3); 337 | # copy IMAGE_LMA to 0x7000:0x100 338 | # segment register fixed to 0x7000 339 | .globl asm_memcpy 340 | asm_memcpy: 341 | pushl %ebp 342 | mov %esp, %ebp 343 | 344 | pushl %esi 345 | pushl %edi 346 | pushl %ecx 347 | 348 | mov $0x7000, %ax 349 | mov %ax, %fs 350 | 351 | mov 8(%ebp), %edi /* Destination */ 352 | mov 12(%ebp), %esi /* Source */ 353 | mov 16(%ebp), %ecx /* Counter */ 354 | MemCpy.1: 355 | cmp $0, %ecx /* Loop counter */ 356 | jz MemCpy.2 357 | movb %ds:(%esi), %al 358 | inc %esi 359 | movb %al, %fs:(%edi) 360 | inc %edi 361 | dec %ecx 362 | jmp MemCpy.1 363 | MemCpy.2: 364 | mov 8(%ebp), %eax 365 | pop %ecx 366 | pop %edi 367 | pop %esi 368 | mov %ebp, %esp 369 | pop %ebp 370 | ret 371 | 372 | .globl asm_absolute_memcpy 373 | # ex: 374 | # asm_absolute_memcpy((u8*)0x100, (u8 *)IMAGE_LMA, 512*3); 375 | # copy IMAGE_LMA to 0x100 376 | asm_absolute_memcpy: 377 | pushl %ebp 378 | mov %esp, %ebp 379 | 380 | pushl %esi 381 | pushl %edi 382 | pushl %ecx 383 | 384 | mov $0, %ax 385 | mov %ax, %fs 386 | 387 | mov 8(%ebp), %edi /* Destination */ 388 | mov 12(%ebp), %esi /* Source */ 389 | mov 16(%ebp), %ecx /* Counter */ 390 | 1: 391 | cmp $0, %ecx /* Loop counter */ 392 | jz 2f 393 | movb %ds:(%esi), %al 394 | inc %esi 395 | movb %al, %fs:(%edi) 396 | inc %edi 397 | dec %ecx 398 | jmp 1b 399 | 2: 400 | mov 8(%ebp), %eax 401 | pop %ecx 402 | pop %edi 403 | pop %esi 404 | mov %ebp, %esp 405 | pop %ebp 406 | ret 407 | 408 | 409 | .text 410 | .globl init_protected_mode 411 | init_protected_mode: 412 | lgdt gdt_ptr 413 | 414 | # clear interrupt flag 415 | cli 416 | 417 | #if 0 418 | # open a20 line 419 | inb $0x92, %al 420 | orb $0b00000010, %al 421 | outb %al, $0x92 422 | #endif 423 | 424 | # enable protect mode 425 | movl %cr0, %eax 426 | orl $1, %eax 427 | movl %eax, %cr0 428 | 429 | #xchg %bx, %bx 430 | #ljmpl $sel_flat_c, $pm_phy_addr 431 | ljmpl $sel_flat_c, $enter_pm_addr 432 | 433 | # movw 16(%ebp), %ecx /* Counter */ 434 | #1: 435 | # cmp $0, %ecx /* Loop counter */ 436 | # jz MemCpy.2 437 | # movb %ds:(%esi), %al 438 | # inc %esi 439 | # movb %al, %es:(%edi) 440 | # inc %edi 441 | # dec %ecx 442 | # jmp MemCpy.1 443 | #2: 444 | # mov 8(%ebp), %eax 445 | # pop %ecx 446 | # pop %edi 447 | # pop %esi 448 | # mov %ebp, %esp 449 | # pop %ebp 450 | # ret 451 | 452 | 453 | 454 | #.bss 455 | #_bss_start_:.word __bss_start__ 456 | #_bss_end_:.word __bss_end__ 457 | 458 | # gdt selector 459 | 460 | #LABEL_STACK: 461 | #.space 512, 0 462 | 463 | 464 | #.section ss 465 | # mov %ax, %es 466 | #.org 510 467 | #.word 0xaa55 468 | 469 | .align 32 470 | .code32 471 | LABEL_PM_START: 472 | mov $sel_video, %ax 473 | mov %ax, %gs 474 | 475 | mov $sel_flat_rw, %ax 476 | mov %ax, %ds 477 | mov %ax, %ss 478 | mov %ax, %es 479 | mov %ax, %fs 480 | 481 | mov $top_of_stack, %esp 482 | 483 | mov $0, %edi 484 | movb $0xc, %ah 485 | movb $'Z', %al 486 | mov %ax, %gs:(%edi) 487 | 488 | call test_p 489 | 490 | .code32 491 | enter_pm: 492 | xchg %bx, %bx 493 | mov $sel_flat_rw, %ax 494 | # mov %fs, %ax 495 | mov %ax, %ds 496 | mov %ax, %es 497 | mov %ax, %ss 498 | 499 | mov %ax, %fs 500 | mov %ax, %gs 501 | # mov %ax, %ss 502 | 503 | mov $top_of_stack, %esp 504 | 505 | #xchg %bx, %bx 506 | jmpl $sel_flat_c, $copy_elf_code_addr # call c func 507 | 508 | .code32 509 | 510 | # prefix p_ is protected 511 | .global p_dump_memory 512 | p_dump_memory: 513 | pushl %ebp 514 | mov %esp, %ebp 515 | 516 | pushl %esi 517 | pushl %edi 518 | pushl %ecx 519 | 520 | mov 8(%ebp), %edi /* Destination */ 521 | mov 12(%ebp), %esi /* Source */ 522 | mov 16(%ebp), %ecx /* Counter */ 523 | 524 | mov $0x100000, %edi /* Destination */ 525 | mov $0x300000, %esi /* Source */ 526 | mov $16, %ecx /* Counter */ 527 | 1: 528 | cmp $0, %ecx /* Loop counter */ 529 | jz 2f 530 | movb %fs:(%esi), %al 531 | 532 | xchg %bx, %bx 533 | call p_disp_al 534 | addl $2, p_vb_addr 535 | 536 | inc %esi 537 | 538 | xor %eax,%eax 539 | 3: 540 | inc %edi 541 | dec %ecx 542 | jmp 1b 543 | 2: 544 | mov 8(%ebp), %eax 545 | pop %ecx 546 | pop %edi 547 | pop %esi 548 | mov %ebp, %esp 549 | pop %ebp 550 | retl 551 | 552 | .global p_disp_ax 553 | p_disp_ax: 554 | xchg %bx, %bx 555 | push %bx 556 | mov %ax, %bx 557 | shr $4, %al 558 | call disp_al 559 | mov %bx, %ax 560 | call p_disp_al 561 | add $2, p_vb_addr 562 | pop %bx 563 | ret 564 | 565 | .global p_disp_al 566 | p_disp_al: 567 | pushl %ecx 568 | pushl %edx 569 | pushl %esi 570 | mov p_vb_addr, %esi 571 | # mov $sel_flat_rw, %cx 572 | # mov %cx, %fs 573 | 574 | movb $0x0c, %ah # 0000: 黑底 1100: 紅字 575 | movb %al, %dl 576 | shr $4, %al 577 | movl $2, %ecx 578 | .begin1: 579 | andb $0x0f, %al 580 | cmp $9, %al 581 | ja 3f # cf=0, zf=0, above 9 (>9) 582 | #addb $'0', %al 583 | addb $0x30, %al 584 | jmp 4f 585 | 3: 586 | sub $0x0A, %al 587 | #add $'A', %al 588 | add $0x41, %al 589 | 4: 590 | #mov [gs:edi], ax 591 | mov %ax, %fs:(%esi) 592 | addl $2, p_vb_addr 593 | mov p_vb_addr, %esi 594 | 595 | 596 | mov %dl, %al 597 | loop .begin1 598 | 599 | popl %esi 600 | popl %edx 601 | popl %ecx 602 | 603 | ret 604 | 605 | enter_pm1: 606 | # mov $select_4g_x, %ax 607 | # mov %ax, %gs 608 | mov $select_4g_rw, %ax 609 | mov %ax, %fs 610 | #mov %ax, %es 611 | 612 | ljmpl $sel_code16,$0 613 | 614 | .data 615 | p_vb: .int 0xb8000 616 | 617 | .code16 618 | LABEL_SEG_CODE16: 619 | mov $sel_normal, %ax 620 | mov %ax, %ds 621 | # mov %ax, %es 622 | mov %ax, %ss 623 | 624 | mov %cr0, %eax 625 | and $0b11111110, %al 626 | mov %eax, %cr0 627 | LABEL_GO_BACK_TO_REAL: 628 | jmp $0, $LABEL_REAL_ENTRY # 段位址會在程序開始處被設置成正確的值 629 | 630 | LABEL_REAL_ENTRY: # 從保護模式跳回到實模式就到了這裡 631 | # xchg %bx, %bx 632 | #mov $0, %eax 633 | mov %cs, %ax 634 | mov %ax, %ds 635 | mov %ax, %es 636 | mov %ax, %ss 637 | sti 638 | jmp big_real_mode 639 | 640 | .global dump_memory 641 | dump_memory: 642 | pushl %ebp 643 | mov %esp, %ebp 644 | 645 | pushl %esi 646 | pushl %edi 647 | pushl %ecx 648 | movl $0xb8000, vb 649 | 650 | mov 8(%ebp), %edi /* Destination */ 651 | mov 12(%ebp), %esi /* Source */ 652 | mov 16(%ebp), %ecx /* Counter */ 653 | 654 | mov $0x100000, %edi /* Destination */ 655 | mov $0x300000, %esi /* Source */ 656 | mov $16, %ecx /* Counter */ 657 | 1: 658 | cmp $0, %ecx /* Loop counter */ 659 | jz 2f 660 | movb %fs:(%esi), %al 661 | 662 | # xchg %bx, %bx 663 | call disp_al 664 | addl $2, vb 665 | 666 | inc %esi 667 | 668 | xor %eax,%eax 669 | 3: 670 | inc %edi 671 | dec %ecx 672 | jmp 1b 673 | 2: 674 | mov 8(%ebp), %eax 675 | pop %ecx 676 | pop %edi 677 | pop %esi 678 | mov %ebp, %esp 679 | pop %ebp 680 | retl 681 | --------------------------------------------------------------------------------