├── 80m.img ├── 80m.img.gz ├── 80m.vhd ├── 80m.vmdk ├── API文档.md ├── LICENSE ├── Makefile ├── Nafs ├── disklog.c ├── link.c ├── main.c ├── misc.c ├── open.c └── read_write.c ├── NanoCore ├── clock.c ├── console.c ├── global.c ├── hd.c ├── i8259.c ├── kernel.asm ├── keyboard.c ├── klib.c ├── kliba.asm ├── main.c ├── proc.c ├── protect.c ├── start.c ├── systask.c └── tty.c ├── Readme.md ├── a.img ├── bochsrc ├── boot ├── boot.asm ├── boot.bin ├── include │ ├── fat12hdr.inc │ ├── load.inc │ └── pm.inc ├── loader.asm └── loader.bin ├── command ├── Makefile ├── echo ├── echo.c ├── inst.tar ├── kernel.bin ├── pwd ├── pwd.c └── start.asm ├── include ├── color.h ├── stdio.h ├── string.h ├── sys │ ├── config.h │ ├── console.h │ ├── const.h │ ├── fs.h │ ├── global.h │ ├── hd.h │ ├── keyboard.h │ ├── keymap.h │ ├── proc.h │ ├── protect.h │ ├── proto.h │ ├── sconst.inc │ └── tty.h └── type.h ├── kernel.bin ├── krnl.map ├── lib ├── NDKcore.a ├── close.c ├── color.c ├── exec.c ├── exit.c ├── fork.c ├── getpid.c ├── misc.c ├── open.c ├── printf.c ├── read.c ├── stat.c ├── string.asm ├── syscall.asm ├── syslog.c ├── unlink.c ├── vsprintf.c ├── wait.c └── write.c ├── mm ├── exec.c ├── forkexit.c └── main.c └── scripts ├── genlog └── splitgraphs /80m.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/80m.img -------------------------------------------------------------------------------- /80m.img.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/80m.img.gz -------------------------------------------------------------------------------- /80m.vhd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/80m.vhd -------------------------------------------------------------------------------- /80m.vmdk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/80m.vmdk -------------------------------------------------------------------------------- /API文档.md: -------------------------------------------------------------------------------- 1 | # NanoOS API Docs 2 | 3 | ## 这是NanoOS的API文档 4 | 5 | ### 欢迎开发者阅读 6 | 7 | > API版本:191229.04 8 | > 9 | > NanoOS适用版本:NanoOS [Blue] Build 19/12/29 Version 191229.04 以及以上 10 | 11 | ![](https://s2.ax1x.com/2019/12/30/lQDoVK.jpg) 12 | 13 | [NanoOS [Blue\] Build 19/12/29 Version 191229.04版本快照]: 14 | 15 | ![](https://s2.ax1x.com/2019/12/29/lKFurQ.png) 16 | 17 | > 本项目Github地址(暂为Private):https://github.com/hanbings/NanoOS 18 | 19 | | 函数名 | 原型 | 20 | | ---------- | ------------------------------------------------------------ | 21 | | sendrec(); | *int* sendrec(*int* function, *int* src_dest, MESSAGE* p_msg); | 22 | | printx(); | *int* printx(*char** str); | 23 | 24 | | 函数名 | 原型 | 25 | | --------- | ---------------------------------------------------------- | 26 | | memcpy(); | void\* memcpy(void\* es:p_dst, void\* ds:p_src, int size); | 27 | | memset(); | void memset(void\* p_dst, char ch, int size); | 28 | | strcpy(); | char* strcpy(*char** dst, const *char** src); | 29 | | strlen(); | *int* strlen(const *char** p_str); | 30 | 31 | | 函数名 | 原型 | 32 | | --------- | ---------------------------------------------------------- | 33 | | open(); | *int* open (const *char* *pathname, *int* flags); | 34 | | read(); | int read (*int* fd, *void* *buf, *int* count); | 35 | | write(); | *int* write (*int* fd, const *void* *buf, *int* count); | 36 | | close(); | *int* close (*int* fd); | 37 | | unlink(); | *int* unlink (const *char* *pathname); | 38 | 39 | | 函数名 | 原型 | 40 | | ------- | ------------------------------- | 41 | | fork(); | *int* fork (); | 42 | | exit(); | *void* exit (*int* status); | 43 | | wait(); | *int* wait (*int* * status); | 44 | 45 | | 函数名 | 原型 | 46 | | --------- | --------------- | 47 | | getpid(); | *int* getpid(); | 48 | 49 | | 函数名 | 原型 | 50 | | ----------- | ------------------------------------------------------------ | 51 | | printf(); | *int* printf(const *char* *fmt, ...); | 52 | | vsprintf(); | *int* vsprintf(*char* *buf, const *char* *fmt, va_list args); | 53 | | spin(); | *void* spin(*char* * func_name); | 54 | 55 | 示例程序:(Linux中的echo,这是简化版本) 56 | 57 | ```c 58 | #include "stdio.h" 59 | int main(int argc, char* argv[]) 60 | { 61 | int i; 62 | for (i = 1; i < argc; i++) 63 | printf("%s%s", i == 1 ? "" : " ", argv[i]); 64 | printf("\n"); 65 | return 0; 66 | } 67 | ``` 68 | 69 | ``` 70 | $echo Hello World 71 | Hello World 72 | ``` 73 | 74 | 示例编译指令 75 | 76 | > 首先您需要确定NDKcore.a确实存在,它位于./lib/NDKcore.a,否则请使用make image编译源代码,再进入./command目录使用make install,而使用make install您必须确保80m.img存在,您也可以修改makeflie 77 | 78 | 直接进入./command目录使用make install编译应用 79 | 80 | END. 81 | 82 | 83 | 84 | **最后,感谢您的耐心阅读和为NanoOS编写软件** 85 | 86 | 87 | 88 | 参考书籍: 89 | 90 | ^《OrangeS:一个操作系统的实现》(于渊)电子工业出版社 2009-6-1 ISBN 9787121084423, 7121084422 91 | 92 | ^《操作系统设计与实现(第3版)》(Andrew S. Tanenbaum)清华大学出版社出版 2008-5-4 ISBN:9787302172765 93 | 94 | ^《一个64位操作系统的设计与实现》(田宇)人民邮电出版社 2018-5 ISBN: 9787115475251 95 | 96 | ^《Intel® 64 and IA-32 Architectures Software Developer Manuals》 (Intel Inc.)2016-10-12 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ######################### 2 | # Makefile for NanoOS # 3 | ######################### 4 | 5 | ENTRYPOINT = 0x1000 6 | 7 | ENTRYOFNafsET = 0x400 8 | 9 | ASM = nasm 10 | DASM = objdump 11 | CC = gcc 12 | LD = ld 13 | ASMBFLAGS = -I boot/include/ 14 | ASMKFLAGS = -I include/ -I include/sys/ -f elf 15 | CFLAGS = -I include/ -I include/sys/ -m32 -c -fno-builtin -Wall -fno-stack-protector 16 | #CFLAGS = -I include/ -c -fno-builtin -fno-stack-protector -fpack-struct -Wall 17 | LDFLAGS = -m elf_i386 -s -Ttext $(ENTRYPOINT) -Map krnl.map 18 | DASMFLAGS = -D 19 | ARFLAGS = rcs 20 | 21 | # This Program 22 | NANOBOOT = boot/boot.bin boot/loader.bin 23 | NANOCOREKernel = kernel.bin 24 | LIB = lib/NDKcore.a 25 | 26 | OBJS = NanoCore/kernel.o NanoCore/start.o NanoCore/main.o\ 27 | NanoCore/clock.o NanoCore/keyboard.o NanoCore/tty.o NanoCore/console.o\ 28 | NanoCore/i8259.o NanoCore/global.o NanoCore/protect.o NanoCore/proc.o\ 29 | NanoCore/systask.o NanoCore/hd.o\ 30 | NanoCore/kliba.o NanoCore/klib.o\ 31 | lib/syslog.o\ 32 | mm/main.o mm/forkexit.o mm/exec.o\ 33 | Nafs/main.o Nafs/open.o Nafs/misc.o Nafs/read_write.o\ 34 | Nafs/link.o\ 35 | Nafs/disklog.o\ 36 | lib/color.o 37 | LOBJS = lib/syscall.o\ 38 | lib/printf.o lib/vsprintf.o\ 39 | lib/string.o lib/misc.o\ 40 | lib/open.o lib/read.o lib/write.o lib/close.o lib/unlink.o\ 41 | lib/getpid.o lib/stat.o\ 42 | lib/fork.o lib/exit.o lib/wait.o lib/exec.o\ 43 | lib/color.o\ 44 | 45 | DASMOUTPUT = kernel.bin.asm 46 | 47 | # All Phony Targets 48 | .PHONY : everything final image clean realclean disasm all buildimg 49 | 50 | # Default starting position 51 | nop : 52 | @echo "why not \`make image' huh? :)" 53 | 54 | everything : $(NANOBOOT) $(NANOCOREKernel) 55 | 56 | all : realclean everything 57 | 58 | image : realclean everything clean buildimg 59 | 60 | clean : 61 | rm -f $(OBJS) $(LOBJS) 62 | 63 | realclean : 64 | rm -f $(OBJS) $(LOBJS) $(LIB) $(NANOBOOT) $(NANOCOREKernel) 65 | 66 | disasm : 67 | $(DASM) $(DASMFLAGS) $(NANOCOREKernel) > $(DASMOUTPUT) 68 | 69 | # We assume that "a.img" exists in current folder 70 | buildimg : 71 | dd if=boot/boot.bin of=a.img bs=512 count=1 conv=notrunc 72 | sudo mount -o loop a.img /mnt/floppy/ 73 | sudo cp -fv boot/loader.bin /mnt/floppy/ 74 | sudo cp -fv NanoCore.bin /mnt/floppy 75 | sudo umount /mnt/floppy 76 | 77 | boot/boot.bin : boot/boot.asm boot/include/load.inc boot/include/fat12hdr.inc 78 | $(ASM) $(ASMBFLAGS) -o $@ $< 79 | 80 | boot/loader.bin : boot/loader.asm boot/include/load.inc boot/include/fat12hdr.inc boot/include/pm.inc 81 | $(ASM) $(ASMBFLAGS) -o $@ $< 82 | 83 | $(NANOCOREKernel) : $(OBJS) $(LIB) 84 | $(LD) $(LDFLAGS) -o $(NANOCOREKernel) $^ 85 | 86 | $(LIB) : $(LOBJS) 87 | $(AR) $(ARFLAGS) $@ $^ 88 | 89 | NanoCore/kernel.o : NanoCore/kernel.asm 90 | $(ASM) $(ASMKFLAGS) -o $@ $< 91 | 92 | lib/syscall.o : lib/syscall.asm 93 | $(ASM) $(ASMKFLAGS) -o $@ $< 94 | 95 | NanoCore/start.o: NanoCore/start.c 96 | $(CC) $(CFLAGS) -o $@ $< 97 | 98 | NanoCore/main.o: NanoCore/main.c 99 | $(CC) $(CFLAGS) -o $@ $< 100 | 101 | NanoCore/clock.o: NanoCore/clock.c 102 | $(CC) $(CFLAGS) -o $@ $< 103 | 104 | NanoCore/keyboard.o: NanoCore/keyboard.c 105 | $(CC) $(CFLAGS) -o $@ $< 106 | 107 | NanoCore/tty.o: NanoCore/tty.c 108 | $(CC) $(CFLAGS) -o $@ $< 109 | 110 | NanoCore/console.o: NanoCore/console.c 111 | $(CC) $(CFLAGS) -o $@ $< 112 | 113 | NanoCore/i8259.o: NanoCore/i8259.c 114 | $(CC) $(CFLAGS) -o $@ $< 115 | 116 | NanoCore/global.o: NanoCore/global.c 117 | $(CC) $(CFLAGS) -o $@ $< 118 | 119 | NanoCore/protect.o: NanoCore/protect.c 120 | $(CC) $(CFLAGS) -o $@ $< 121 | 122 | NanoCore/proc.o: NanoCore/proc.c 123 | $(CC) $(CFLAGS) -o $@ $< 124 | 125 | lib/printf.o: lib/printf.c 126 | $(CC) $(CFLAGS) -o $@ $< 127 | 128 | lib/vsprintf.o: lib/vsprintf.c 129 | $(CC) $(CFLAGS) -o $@ $< 130 | 131 | NanoCore/systask.o: NanoCore/systask.c 132 | $(CC) $(CFLAGS) -o $@ $< 133 | 134 | NanoCore/hd.o: NanoCore/hd.c 135 | $(CC) $(CFLAGS) -o $@ $< 136 | 137 | NanoCore/klib.o: NanoCore/klib.c 138 | $(CC) $(CFLAGS) -o $@ $< 139 | 140 | lib/misc.o: lib/misc.c 141 | $(CC) $(CFLAGS) -o $@ $< 142 | 143 | NanoCore/kliba.o : NanoCore/kliba.asm 144 | $(ASM) $(ASMKFLAGS) -o $@ $< 145 | 146 | lib/string.o : lib/string.asm 147 | $(ASM) $(ASMKFLAGS) -o $@ $< 148 | 149 | lib/open.o: lib/open.c 150 | $(CC) $(CFLAGS) -o $@ $< 151 | 152 | lib/read.o: lib/read.c 153 | $(CC) $(CFLAGS) -o $@ $< 154 | 155 | lib/write.o: lib/write.c 156 | $(CC) $(CFLAGS) -o $@ $< 157 | 158 | lib/close.o: lib/close.c 159 | $(CC) $(CFLAGS) -o $@ $< 160 | 161 | lib/unlink.o: lib/unlink.c 162 | $(CC) $(CFLAGS) -o $@ $< 163 | 164 | lib/getpid.o: lib/getpid.c 165 | $(CC) $(CFLAGS) -o $@ $< 166 | 167 | lib/syslog.o: lib/syslog.c 168 | $(CC) $(CFLAGS) -o $@ $< 169 | 170 | lib/fork.o: lib/fork.c 171 | $(CC) $(CFLAGS) -o $@ $< 172 | 173 | lib/exit.o: lib/exit.c 174 | $(CC) $(CFLAGS) -o $@ $< 175 | 176 | lib/wait.o: lib/wait.c 177 | $(CC) $(CFLAGS) -o $@ $< 178 | 179 | lib/exec.o: lib/exec.c 180 | $(CC) $(CFLAGS) -o $@ $< 181 | 182 | lib/stat.o: lib/stat.c 183 | $(CC) $(CFLAGS) -o $@ $< 184 | 185 | mm/main.o: mm/main.c 186 | $(CC) $(CFLAGS) -o $@ $< 187 | 188 | mm/forkexit.o: mm/forkexit.c 189 | $(CC) $(CFLAGS) -o $@ $< 190 | 191 | mm/exec.o: mm/exec.c 192 | $(CC) $(CFLAGS) -o $@ $< 193 | 194 | Nafs/main.o: Nafs/main.c 195 | $(CC) $(CFLAGS) -o $@ $< 196 | 197 | Nafs/open.o: Nafs/open.c 198 | $(CC) $(CFLAGS) -o $@ $< 199 | 200 | Nafs/read_write.o: Nafs/read_write.c 201 | $(CC) $(CFLAGS) -o $@ $< 202 | 203 | Nafs/link.o: Nafs/link.c 204 | $(CC) $(CFLAGS) -o $@ $< 205 | 206 | Nafs/disklog.o: Nafs/disklog.c 207 | $(CC) $(CFLAGS) -o $@ $< 208 | 209 | lib/color.o: lib/color.c 210 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /Nafs/link.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | 17 | /***************************************************************************** 18 | * do_unlink 19 | *****************************************************************************/ 20 | /** 21 | * Remove a file. 22 | * 23 | * @note We clear the i-node in inode_array[] although it is not really needed. 24 | * We don't clear the data bytes so the file is recoverable. 25 | * 26 | * @return On success, zero is returned. On error, -1 is returned. 27 | *****************************************************************************/ 28 | PUBLIC int do_unlink() 29 | { 30 | char pathname[MAX_PATH]; 31 | 32 | /* get parameters from the message */ 33 | int name_len = fs_msg.NAME_LEN; /* length of filename */ 34 | int src = fs_msg.source; /* caller proc nr. */ 35 | assert(name_len < MAX_PATH); 36 | phys_copy((void*)va2la(TASK_FS, pathname), 37 | (void*)va2la(src, fs_msg.PATHNAME), 38 | name_len); 39 | pathname[name_len] = 0; 40 | 41 | if (strcmp(pathname , "/") == 0) { 42 | printl("[INFO][FS] FS:do_unlink():: cannot unlink the root\n"); 43 | return -1; 44 | } 45 | 46 | int inode_nr = search_file(pathname); 47 | if (inode_nr == INVALID_INODE) { /* file not found */ 48 | printl("[INFO][FS] FS::do_unlink():: search_file() returns " 49 | "invalid inode: %s\n", pathname); 50 | return -1; 51 | } 52 | 53 | char filename[MAX_PATH]; 54 | struct inode * dir_inode; 55 | if (strip_path(filename, pathname, &dir_inode) != 0) 56 | return -1; 57 | 58 | struct inode * pin = get_inode(dir_inode->i_dev, inode_nr); 59 | 60 | if (pin->i_mode != I_REGULAR) { /* can only remove regular files */ 61 | printl("[INFO][FS] cannot remove file %s, because " 62 | "it is not a regular file.\n", 63 | pathname); 64 | return -1; 65 | } 66 | 67 | if (pin->i_cnt > 1) { /* the file was opened */ 68 | printl("[INFO][FS] cannot remove file %s, because pin->i_cnt is %d.\n", 69 | pathname, pin->i_cnt); 70 | return -1; 71 | } 72 | 73 | struct super_block * sb = get_super_block(pin->i_dev); 74 | 75 | /*************************/ 76 | /* free the bit in i-map */ 77 | /*************************/ 78 | int byte_idx = inode_nr / 8; 79 | int bit_idx = inode_nr % 8; 80 | assert(byte_idx < SECTOR_SIZE); /* we have only one i-map sector */ 81 | /* read sector 2 (skip bootsect and superblk): */ 82 | RD_SECT(pin->i_dev, 2); 83 | assert(fsbuf[byte_idx % SECTOR_SIZE] & (1 << bit_idx)); 84 | fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << bit_idx); 85 | WR_SECT(pin->i_dev, 2); 86 | 87 | /**************************/ 88 | /* free the bits in s-map */ 89 | /**************************/ 90 | /* 91 | * bit_idx: bit idx in the entire i-map 92 | * ... ____|____ 93 | * \ .-- byte_cnt: how many bytes between 94 | * \ | the first and last byte 95 | * +-+-+-+-+-+-+-+-+ V +-+-+-+-+-+-+-+-+ 96 | * ... | | | | | |*|*|*|...|*|*|*|*| | | | | 97 | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 98 | * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 99 | * ...__/ 100 | * byte_idx: byte idx in the entire i-map 101 | */ 102 | bit_idx = pin->i_start_sect - sb->n_1st_sect + 1; 103 | byte_idx = bit_idx / 8; 104 | int bits_left = pin->i_nr_sects; 105 | int byte_cnt = (bits_left - (8 - (bit_idx % 8))) / 8; 106 | 107 | /* current sector nr. */ 108 | int s = 2 /* 2: bootsect + superblk */ 109 | + sb->nr_imap_sects + byte_idx / SECTOR_SIZE; 110 | 111 | RD_SECT(pin->i_dev, s); 112 | 113 | int i; 114 | /* clear the first byte */ 115 | for (i = bit_idx % 8; (i < 8) && bits_left; i++,bits_left--) { 116 | assert((fsbuf[byte_idx % SECTOR_SIZE] >> i & 1) == 1); 117 | fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << i); 118 | } 119 | 120 | /* clear bytes from the second byte to the second to last */ 121 | int k; 122 | i = (byte_idx % SECTOR_SIZE) + 1; /* the second byte */ 123 | for (k = 0; k < byte_cnt; k++,i++,bits_left-=8) { 124 | if (i == SECTOR_SIZE) { 125 | i = 0; 126 | WR_SECT(pin->i_dev, s); 127 | RD_SECT(pin->i_dev, ++s); 128 | } 129 | assert(fsbuf[i] == 0xFF); 130 | fsbuf[i] = 0; 131 | } 132 | 133 | /* clear the last byte */ 134 | if (i == SECTOR_SIZE) { 135 | i = 0; 136 | WR_SECT(pin->i_dev, s); 137 | RD_SECT(pin->i_dev, ++s); 138 | } 139 | unsigned char mask = ~((unsigned char)(~0) << bits_left); 140 | assert((fsbuf[i] & mask) == mask); 141 | fsbuf[i] &= (~0) << bits_left; 142 | WR_SECT(pin->i_dev, s); 143 | 144 | /***************************/ 145 | /* clear the i-node itself */ 146 | /***************************/ 147 | pin->i_mode = 0; 148 | pin->i_size = 0; 149 | pin->i_start_sect = 0; 150 | pin->i_nr_sects = 0; 151 | sync_inode(pin); 152 | /* release slot in inode_table[] */ 153 | put_inode(pin); 154 | 155 | /************************************************/ 156 | /* set the inode-nr to 0 in the directory entry */ 157 | /************************************************/ 158 | int dir_blk0_nr = dir_inode->i_start_sect; 159 | int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; 160 | int nr_dir_entries = 161 | dir_inode->i_size / DIR_ENTRY_SIZE; /* including unused slots 162 | * (the file has been 163 | * deleted but the slot 164 | * is still there) 165 | */ 166 | int m = 0; 167 | struct dir_entry * pde = 0; 168 | int flg = 0; 169 | int dir_size = 0; 170 | 171 | for (i = 0; i < nr_dir_blks; i++) { 172 | RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); 173 | 174 | pde = (struct dir_entry *)fsbuf; 175 | int j; 176 | for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) { 177 | if (++m > nr_dir_entries) 178 | break; 179 | 180 | if (pde->inode_nr == inode_nr) { 181 | /* pde->inode_nr = 0; */ 182 | memset(pde, 0, DIR_ENTRY_SIZE); 183 | WR_SECT(dir_inode->i_dev, dir_blk0_nr + i); 184 | flg = 1; 185 | break; 186 | } 187 | 188 | if (pde->inode_nr != INVALID_INODE) 189 | dir_size += DIR_ENTRY_SIZE; 190 | } 191 | 192 | if (m > nr_dir_entries || /* all entries have been iterated OR */ 193 | flg) /* file is found */ 194 | break; 195 | } 196 | assert(flg); 197 | if (m == nr_dir_entries) { /* the file is the last one in the dir */ 198 | dir_inode->i_size = dir_size; 199 | sync_inode(dir_inode); 200 | } 201 | 202 | return 0; 203 | } 204 | -------------------------------------------------------------------------------- /Nafs/misc.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | #include "hd.h" 16 | #include "fs.h" 17 | 18 | /***************************************************************************** 19 | * do_stat 20 | *************************************************************************//** 21 | * Perform the stat() syscall. 22 | * 23 | * @return On success, zero is returned. On error, -1 is returned. 24 | *****************************************************************************/ 25 | PUBLIC int do_stat() 26 | { 27 | char pathname[MAX_PATH]; /* parameter from the caller */ 28 | char filename[MAX_PATH]; /* directory has been stipped */ 29 | 30 | /* get parameters from the message */ 31 | int name_len = fs_msg.NAME_LEN; /* length of filename */ 32 | int src = fs_msg.source; /* caller proc nr. */ 33 | assert(name_len < MAX_PATH); 34 | phys_copy((void*)va2la(TASK_FS, pathname), /* to */ 35 | (void*)va2la(src, fs_msg.PATHNAME), /* from */ 36 | name_len); 37 | pathname[name_len] = 0; /* terminate the string */ 38 | 39 | int inode_nr = search_file(pathname); 40 | if (inode_nr == INVALID_INODE) { /* file not found */ 41 | printl("[INFO][FS] FS::do_stat():: search_file() returns " 42 | "invalid inode: %s\n", pathname); 43 | return -1; 44 | } 45 | 46 | struct inode * pin = 0; 47 | 48 | struct inode * dir_inode; 49 | if (strip_path(filename, pathname, &dir_inode) != 0) { 50 | /* theoretically never fail here 51 | * (it would have failed earlier when 52 | * search_file() was called) 53 | */ 54 | assert(0); 55 | } 56 | pin = get_inode(dir_inode->i_dev, inode_nr); 57 | 58 | struct stat s; /* the thing requested */ 59 | s.st_dev = pin->i_dev; 60 | s.st_ino = pin->i_num; 61 | s.st_mode= pin->i_mode; 62 | s.st_rdev= is_special(pin->i_mode) ? pin->i_start_sect : NO_DEV; 63 | s.st_size= pin->i_size; 64 | 65 | put_inode(pin); 66 | 67 | phys_copy((void*)va2la(src, fs_msg.BUF), /* to */ 68 | (void*)va2la(TASK_FS, &s), /* from */ 69 | sizeof(struct stat)); 70 | 71 | return 0; 72 | } 73 | 74 | /***************************************************************************** 75 | * search_file 76 | *****************************************************************************/ 77 | /** 78 | * Search the file and return the inode_nr. 79 | * 80 | * @param[in] path The full path of the file to search. 81 | * @return Ptr to the i-node of the file if successful, otherwise zero. 82 | * 83 | * @see open() 84 | * @see do_open() 85 | *****************************************************************************/ 86 | PUBLIC int search_file(char * path) 87 | { 88 | int i, j; 89 | 90 | char filename[MAX_PATH]; 91 | memset(filename, 0, MAX_FILENAME_LEN); 92 | struct inode * dir_inode; 93 | if (strip_path(filename, path, &dir_inode) != 0) 94 | return 0; 95 | 96 | if (filename[0] == 0) /* path: "/" */ 97 | return dir_inode->i_num; 98 | 99 | /** 100 | * Search the dir for the file. 101 | */ 102 | int dir_blk0_nr = dir_inode->i_start_sect; 103 | int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE - 1) / SECTOR_SIZE; 104 | int nr_dir_entries = 105 | dir_inode->i_size / DIR_ENTRY_SIZE; /** 106 | * including unused slots 107 | * (the file has been deleted 108 | * but the slot is still there) 109 | */ 110 | int m = 0; 111 | struct dir_entry * pde; 112 | for (i = 0; i < nr_dir_blks; i++) { 113 | RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); 114 | pde = (struct dir_entry *)fsbuf; 115 | for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) { 116 | if (memcmp(filename, pde->name, MAX_FILENAME_LEN) == 0) 117 | return pde->inode_nr; 118 | if (++m > nr_dir_entries) 119 | break; 120 | } 121 | if (m > nr_dir_entries) /* all entries have been iterated */ 122 | break; 123 | } 124 | 125 | /* file not found */ 126 | return 0; 127 | } 128 | 129 | /***************************************************************************** 130 | * strip_path 131 | *****************************************************************************/ 132 | /** 133 | * Get the basename from the fullpath. 134 | * 135 | * In Orange'S FS v1.0, all files are stored in the root directory. 136 | * There is no sub-folder thing. 137 | * 138 | * This routine should be called at the very beginning of file operations 139 | * such as open(), read() and write(). It accepts the full path and returns 140 | * two things: the basename and a ptr of the root dir's i-node. 141 | * 142 | * e.g. After stip_path(filename, "/blah", ppinode) finishes, we get: 143 | * - filename: "blah" 144 | * - *ppinode: root_inode 145 | * - ret val: 0 (successful) 146 | * 147 | * Currently an acceptable pathname should begin with at most one `/' 148 | * preceding a filename. 149 | * 150 | * Filenames may contain any character except '/' and '\\0'. 151 | * 152 | * @param[out] filename The string for the result. 153 | * @param[in] pathname The full pathname. 154 | * @param[out] ppinode The ptr of the dir's inode will be stored here. 155 | * 156 | * @return Zero if success, otherwise the pathname is not valid. 157 | *****************************************************************************/ 158 | PUBLIC int strip_path(char * filename, const char * pathname, 159 | struct inode** ppinode) 160 | { 161 | const char * s = pathname; 162 | char * t = filename; 163 | 164 | if (s == 0) 165 | return -1; 166 | 167 | if (*s == '/') 168 | s++; 169 | 170 | while (*s) { /* check each character */ 171 | if (*s == '/') 172 | return -1; 173 | *t++ = *s++; 174 | /* if filename is too long, just truncate it */ 175 | if (t - filename >= MAX_FILENAME_LEN) 176 | break; 177 | } 178 | *t = 0; 179 | 180 | *ppinode = root_inode; 181 | 182 | return 0; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /Nafs/read_write.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | 17 | /***************************************************************************** 18 | * do_rdwt 19 | *****************************************************************************/ 20 | /** 21 | * Read/Write file and return byte count read/written. 22 | * 23 | * Sector map is not needed to update, since the sectors for the file have been 24 | * allocated and the bits are set when the file was created. 25 | * 26 | * @return How many bytes have been read/written. 27 | *****************************************************************************/ 28 | PUBLIC int do_rdwt() 29 | { 30 | int fd = fs_msg.FD; /**< file descriptor. */ 31 | void * buf = fs_msg.BUF;/**< r/w buffer */ 32 | int len = fs_msg.CNT; /**< r/w bytes */ 33 | 34 | int src = fs_msg.source; /* caller proc nr. */ 35 | 36 | assert((pcaller->filp[fd] >= &f_desc_table[0]) && 37 | (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC])); 38 | 39 | if (!(pcaller->filp[fd]->fd_mode & O_RDWR)) 40 | return 0; 41 | 42 | int pos = pcaller->filp[fd]->fd_pos; 43 | 44 | struct inode * pin = pcaller->filp[fd]->fd_inode; 45 | 46 | assert(pin >= &inode_table[0] && pin < &inode_table[NR_INODE]); 47 | 48 | int imode = pin->i_mode & I_TYPE_MASK; 49 | 50 | if (imode == I_CHAR_SPECIAL) { 51 | int t = fs_msg.type == READ ? DEV_READ : DEV_WRITE; 52 | fs_msg.type = t; 53 | 54 | int dev = pin->i_start_sect; 55 | assert(MAJOR(dev) == 4); 56 | 57 | fs_msg.DEVICE = MINOR(dev); 58 | fs_msg.BUF = buf; 59 | fs_msg.CNT = len; 60 | fs_msg.PROC_NR = src; 61 | assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER); 62 | send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &fs_msg); 63 | assert(fs_msg.CNT == len); 64 | 65 | return fs_msg.CNT; 66 | } 67 | else { 68 | assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY); 69 | assert((fs_msg.type == READ) || (fs_msg.type == WRITE)); 70 | 71 | int pos_end; 72 | if (fs_msg.type == READ) 73 | pos_end = min(pos + len, pin->i_size); 74 | else /* WRITE */ 75 | pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); 76 | 77 | int off = pos % SECTOR_SIZE; 78 | int rw_sect_min=pin->i_start_sect+(pos>>SECTOR_SIZE_SHIFT); 79 | int rw_sect_max=pin->i_start_sect+(pos_end>>SECTOR_SIZE_SHIFT); 80 | 81 | int chunk = min(rw_sect_max - rw_sect_min + 1, 82 | FSBUF_SIZE >> SECTOR_SIZE_SHIFT); 83 | 84 | int bytes_rw = 0; 85 | int bytes_left = len; 86 | int i; 87 | for (i = rw_sect_min; i <= rw_sect_max; i += chunk) { 88 | /* read/write this amount of bytes every time */ 89 | int bytes = min(bytes_left, chunk * SECTOR_SIZE - off); 90 | rw_sector(DEV_READ, 91 | pin->i_dev, 92 | i * SECTOR_SIZE, 93 | chunk * SECTOR_SIZE, 94 | TASK_FS, 95 | fsbuf); 96 | 97 | if (fs_msg.type == READ) { 98 | phys_copy((void*)va2la(src, buf + bytes_rw), 99 | (void*)va2la(TASK_FS, fsbuf + off), 100 | bytes); 101 | } 102 | else { /* WRITE */ 103 | phys_copy((void*)va2la(TASK_FS, fsbuf + off), 104 | (void*)va2la(src, buf + bytes_rw), 105 | bytes); 106 | rw_sector(DEV_WRITE, 107 | pin->i_dev, 108 | i * SECTOR_SIZE, 109 | chunk * SECTOR_SIZE, 110 | TASK_FS, 111 | fsbuf); 112 | } 113 | off = 0; 114 | bytes_rw += bytes; 115 | pcaller->filp[fd]->fd_pos += bytes; 116 | bytes_left -= bytes; 117 | } 118 | 119 | if (pcaller->filp[fd]->fd_pos > pin->i_size) { 120 | /* update inode::size */ 121 | pin->i_size = pcaller->filp[fd]->fd_pos; 122 | /* write the updated i-node back to disk */ 123 | sync_inode(pin); 124 | } 125 | 126 | return bytes_rw; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /NanoCore/clock.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * clock_handler 18 | *****************************************************************************/ 19 | /** 20 | * This routine handles the clock interrupt generated by 8253/8254 21 | * programmable interval timer. 22 | * 23 | * @param irq The IRQ nr, unused here. 24 | *****************************************************************************/ 25 | PUBLIC void clock_handler(int irq) 26 | { 27 | if (++ticks >= MAX_TICKS) 28 | ticks = 0; 29 | 30 | if (p_proc_ready->ticks) 31 | p_proc_ready->ticks--; 32 | 33 | if (key_pressed) 34 | inform_int(TASK_TTY); 35 | 36 | if (k_reenter != 0) { 37 | return; 38 | } 39 | 40 | if (p_proc_ready->ticks > 0) { 41 | return; 42 | } 43 | 44 | schedule(); 45 | 46 | } 47 | 48 | /***************************************************************************** 49 | * milli_delay 50 | *****************************************************************************/ 51 | /** 52 | * Delay for a specified amount of time. 53 | * 54 | * @param milli_sec How many milliseconds to delay. 55 | *****************************************************************************/ 56 | PUBLIC void milli_delay(int milli_sec) 57 | { 58 | int t = get_ticks(); 59 | 60 | while(((get_ticks() - t) * 1000 / HZ) < milli_sec) {} 61 | } 62 | 63 | /***************************************************************************** 64 | * init_clock 65 | *****************************************************************************/ 66 | /** 67 | * Initialize 8253/8254 PIT (Programmable Interval Timer). 68 | * 69 | *****************************************************************************/ 70 | PUBLIC void init_clock() 71 | { 72 | /* 初始化 8253 PIT */ 73 | out_byte(TIMER_MODE, RATE_GENERATOR); 74 | out_byte(TIMER0, (u8) (TIMER_FREQ/HZ) ); 75 | out_byte(TIMER0, (u8) ((TIMER_FREQ/HZ) >> 8)); 76 | 77 | put_irq_handler(CLOCK_IRQ, clock_handler); /* 设定时钟中断处理程序 */ 78 | enable_irq(CLOCK_IRQ); /* 让8259A可以接收时钟中断 */ 79 | } 80 | 81 | 82 | -------------------------------------------------------------------------------- /NanoCore/global.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #define GLOBAL_VARIABLES_HERE 3 | 4 | #include "type.h" 5 | #include "stdio.h" 6 | #include "const.h" 7 | #include "protect.h" 8 | #include "fs.h" 9 | #include "tty.h" 10 | #include "console.h" 11 | #include "proc.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | PUBLIC struct proc proc_table[NR_TASKS + NR_PROCS]; 17 | 18 | /* 注意下面的 TASK 的顺序要与 const.h 中对应 */ 19 | PUBLIC struct task task_table[NR_TASKS] = { 20 | /* entry stack size task name */ 21 | /* ----- ---------- --------- */ 22 | {task_tty, STACK_SIZE_TTY, "TTY" }, 23 | {task_sys, STACK_SIZE_SYS, "SYS" }, 24 | {task_hd, STACK_SIZE_HD, "HD" }, 25 | {task_fs, STACK_SIZE_FS, "FS" }, 26 | {task_mm, STACK_SIZE_MM, "MM" }}; 27 | 28 | PUBLIC struct task user_proc_table[NR_NATIVE_PROCS] = { 29 | /* entry stack size proc name */ 30 | /* ----- ---------- --------- */ 31 | {Init, STACK_SIZE_INIT, "INIT" }, 32 | {TestA, STACK_SIZE_TESTA, "TestA"}, 33 | {TestB, STACK_SIZE_TESTB, "TestB"}, 34 | {TestC, STACK_SIZE_TESTC, "TestC"}}; 35 | /* PUBLIC struct task user_proc_table[NR_PROCS] = { */ 36 | /* {TestA, STACK_SIZE_TESTA, "TestA"}, */ 37 | /* {TestB, STACK_SIZE_TESTB, "TestB"}, */ 38 | /* {TestC, STACK_SIZE_TESTC, "TestC"}}; */ 39 | 40 | PUBLIC char task_stack[STACK_SIZE_TOTAL]; 41 | 42 | PUBLIC TTY tty_table[NR_CONSOLES]; 43 | PUBLIC CONSOLE console_table[NR_CONSOLES]; 44 | 45 | PUBLIC irq_handler irq_table[NR_IRQ]; 46 | 47 | PUBLIC system_call sys_call_table[NR_SYS_CALL] = {sys_printx, 48 | sys_sendrec}; 49 | 50 | /* FS related below */ 51 | /*****************************************************************************/ 52 | /** 53 | * For dd_map[k], 54 | * `k' is the device nr.\ dd_map[k].driver_nr is the driver nr. 55 | * 56 | * Remeber to modify include/const.h if the order is changed. 57 | *****************************************************************************/ 58 | struct dev_drv_map dd_map[] = { 59 | /* driver nr. major device nr. 60 | ---------- ---------------- */ 61 | {INVALID_DRIVER}, /**< 0 : Unused */ 62 | {INVALID_DRIVER}, /**< 1 : Reserved for floppy driver */ 63 | {INVALID_DRIVER}, /**< 2 : Reserved for cdrom driver */ 64 | {TASK_HD}, /**< 3 : Hard disk */ 65 | {TASK_TTY}, /**< 4 : TTY */ 66 | {INVALID_DRIVER} /**< 5 : Reserved for scsi disk driver */ 67 | }; 68 | 69 | /** 70 | * 6MB~7MB: buffer for FS 71 | */ 72 | PUBLIC u8 * fsbuf = (u8*)0x600000; 73 | PUBLIC const int FSBUF_SIZE = 0x100000; 74 | 75 | 76 | /** 77 | * 7MB~8MB: buffer for MM 78 | */ 79 | PUBLIC u8 * mmbuf = (u8*)0x700000; 80 | PUBLIC const int MMBUF_SIZE = 0x100000; 81 | 82 | 83 | /** 84 | * 8MB~10MB: buffer for log (debug) 85 | */ 86 | PUBLIC char * logbuf = (char*)0x800000; 87 | PUBLIC const int LOGBUF_SIZE = 0x100000; 88 | PUBLIC char * logdiskbuf = (char*)0x900000; 89 | PUBLIC const int LOGDISKBUF_SIZE = 0x100000; 90 | 91 | -------------------------------------------------------------------------------- /NanoCore/i8259.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | 4 | #include "type.h" 5 | #include "stdio.h" 6 | #include "const.h" 7 | #include "protect.h" 8 | #include "proc.h" 9 | #include "fs.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /*======================================================================* 17 | init_8259A 18 | *======================================================================*/ 19 | PUBLIC void init_8259A() 20 | { 21 | out_byte(INT_M_CTL, 0x11); /* Master 8259, ICW1. */ 22 | out_byte(INT_S_CTL, 0x11); /* Slave 8259, ICW1. */ 23 | out_byte(INT_M_CTLMASK, INT_VECTOR_IRQ0); /* Master 8259, ICW2. 设置 '主8259' 的中断入口地址为 0x20. */ 24 | out_byte(INT_S_CTLMASK, INT_VECTOR_IRQ8); /* Slave 8259, ICW2. 设置 '从8259' 的中断入口地址为 0x28. */ 25 | out_byte(INT_M_CTLMASK, 0x4); /* Master 8259, ICW3. IR2 对应 '从8259'. */ 26 | out_byte(INT_S_CTLMASK, 0x2); /* Slave 8259, ICW3. 对应 '主8259' 的 IR2. */ 27 | out_byte(INT_M_CTLMASK, 0x1); /* Master 8259, ICW4. */ 28 | out_byte(INT_S_CTLMASK, 0x1); /* Slave 8259, ICW4. */ 29 | 30 | out_byte(INT_M_CTLMASK, 0xFF); /* Master 8259, OCW1. */ 31 | out_byte(INT_S_CTLMASK, 0xFF); /* Slave 8259, OCW1. */ 32 | 33 | int i; 34 | for (i = 0; i < NR_IRQ; i++) { 35 | irq_table[i] = spurious_irq; 36 | } 37 | } 38 | 39 | /*======================================================================* 40 | spurious_irq 41 | *======================================================================*/ 42 | PUBLIC void spurious_irq(int irq) 43 | { 44 | disp_str("[INFO][Core]spurious_IRQ: "); 45 | disp_int(irq); 46 | disp_str("\n"); 47 | } 48 | 49 | /*======================================================================* 50 | put_irq_handler 51 | *======================================================================*/ 52 | PUBLIC void put_irq_handler(int irq, irq_handler handler) 53 | { 54 | disable_irq(irq); 55 | irq_table[irq] = handler; 56 | } 57 | -------------------------------------------------------------------------------- /NanoCore/kernel.asm: -------------------------------------------------------------------------------- 1 | 2 | ;/*Hanbings 3219065882@qq.com*/ 3 | 4 | 5 | %include "sconst.inc" 6 | 7 | ; 导入函数 8 | extern cstart 9 | extern kernel_main 10 | extern exception_handler 11 | extern spurious_irq 12 | extern clock_handler 13 | extern disp_str 14 | extern delay 15 | extern irq_table 16 | 17 | ; 导入全局变量 18 | extern gdt_ptr 19 | extern idt_ptr 20 | extern p_proc_ready 21 | extern tss 22 | extern disp_pos 23 | extern k_reenter 24 | extern sys_call_table 25 | 26 | bits 32 27 | 28 | [SECTION .data] 29 | clock_int_msg db "^", 0 30 | 31 | [SECTION .bss] 32 | StackSpace resb 2 * 1024 33 | StackTop: ; 栈顶 34 | 35 | [section .text] ; 代码在此 36 | 37 | global _start ; 导出 _start 38 | 39 | global restart 40 | global sys_call 41 | 42 | global divide_error 43 | global single_step_exception 44 | global nmi 45 | global breakpoint_exception 46 | global overflow 47 | global bounds_check 48 | global inval_opcode 49 | global copr_not_available 50 | global double_fault 51 | global copr_seg_overrun 52 | global inval_tss 53 | global segment_not_present 54 | global stack_exception 55 | global general_protection 56 | global page_fault 57 | global copr_error 58 | global hwint00 59 | global hwint01 60 | global hwint02 61 | global hwint03 62 | global hwint04 63 | global hwint05 64 | global hwint06 65 | global hwint07 66 | global hwint08 67 | global hwint09 68 | global hwint10 69 | global hwint11 70 | global hwint12 71 | global hwint13 72 | global hwint14 73 | global hwint15 74 | 75 | 76 | _start: 77 | ; 此时内存看上去是这样的(更详细的内存情况在 LOADER.ASM 中有说明): 78 | ; ┃ ┃ 79 | ; ┃ ... ┃ 80 | ; ┣━━━━━━━━━━━━━━━━━━┫ 81 | ; ┃■■■■■■Page Tables■■■■■■┃ 82 | ; ┃■■■■■(大小由LOADER决定)■■■■┃ PageTblBase 83 | ; 00101000h ┣━━━━━━━━━━━━━━━━━━┫ 84 | ; ┃■■■■Page Directory Table■■■■┃ PageDirBase = 1M 85 | ; 00100000h ┣━━━━━━━━━━━━━━━━━━┫ 86 | ; ┃□□□□ Hardware Reserved □□□□┃ B8000h ← gs 87 | ; 9FC00h ┣━━━━━━━━━━━━━━━━━━┫ 88 | ; ┃■■■■■■■LOADER.BIN■■■■■■┃ somewhere in LOADER ← esp 89 | ; 90000h ┣━━━━━━━━━━━━━━━━━━┫ 90 | ; ┃■■■■■■■KERNEL.BIN■■■■■■┃ 91 | ; 80000h ┣━━━━━━━━━━━━━━━━━━┫ 92 | ; ┃■■■■■■■■KERNEL■■■■■■■┃ 30400h ← KERNEL 入口 (KernelEntryPointPhyAddr) 93 | ; 30000h ┣━━━━━━━━━━━━━━━━━━┫ 94 | ; ┋ ... ┋ 95 | ; ┋ ┋ 96 | ; 0h ┗━━━━━━━━━━━━━━━━━━┛ ← cs, ds, es, fs, ss 97 | ; 98 | ; 99 | ; GDT 以及相应的描述符是这样的: 100 | ; 101 | ; Descriptors Selectors 102 | ; ┏━━━━━━━━━━━━━━━━━━┓ 103 | ; ┃ Dummy Descriptor ┃ 104 | ; ┣━━━━━━━━━━━━━━━━━━┫ 105 | ; ┃ DESC_FLAT_C (0~4G) ┃ 8h = cs 106 | ; ┣━━━━━━━━━━━━━━━━━━┫ 107 | ; ┃ DESC_FLAT_RW (0~4G) ┃ 10h = ds, es, fs, ss 108 | ; ┣━━━━━━━━━━━━━━━━━━┫ 109 | ; ┃ DESC_VIDEO ┃ 1Bh = gs 110 | ; ┗━━━━━━━━━━━━━━━━━━┛ 111 | ; 112 | ; 注意! 在使用 C 代码的时候一定要保证 ds, es, ss 这几个段寄存器的值是一样的 113 | ; 因为编译器有可能编译出使用它们的代码, 而编译器默认它们是一样的. 比如串拷贝操作会用到 ds 和 es. 114 | ; 115 | ; 116 | 117 | 118 | ; 把 esp 从 LOADER 挪到 KERNEL 119 | mov esp, StackTop ; 堆栈在 bss 段中 120 | 121 | mov dword [disp_pos], 0 122 | 123 | sgdt [gdt_ptr] ; cstart() 中将会用到 gdt_ptr 124 | call cstart ; 在此函数中改变了gdt_ptr,让它指向新的GDT 125 | lgdt [gdt_ptr] ; 使用新的GDT 126 | 127 | lidt [idt_ptr] 128 | 129 | jmp SELECTOR_KERNEL_CS:csinit 130 | csinit: ; “这个跳转指令强制使用刚刚初始化的结构”——<> P90. 131 | 132 | ;jmp 0x40:0 133 | ;ud2 134 | 135 | 136 | xor eax, eax 137 | mov ax, SELECTOR_TSS 138 | ltr ax 139 | 140 | ;sti 141 | jmp kernel_main 142 | 143 | ;hlt 144 | 145 | 146 | ; 中断和异常 -- 硬件中断 147 | ; --------------------------------- 148 | %macro hwint_master 1 149 | call save 150 | in al, INT_M_CTLMASK ; `. 151 | or al, (1 << %1) ; | 屏蔽当前中断 152 | out INT_M_CTLMASK, al ; / 153 | mov al, EOI ; `. 置EOI位 154 | out INT_M_CTL, al ; / 155 | sti ; CPU在响应中断的过程中会自动关中断,这句之后就允许响应新的中断 156 | push %1 ; `. 157 | call [irq_table + 4 * %1] ; | 中断处理程序 158 | pop ecx ; / 159 | cli 160 | in al, INT_M_CTLMASK ; `. 161 | and al, ~(1 << %1) ; | 恢复接受当前中断 162 | out INT_M_CTLMASK, al ; / 163 | ret 164 | %endmacro 165 | 166 | 167 | ALIGN 16 168 | hwint00: ; Interrupt routine for irq 0 (the clock). 169 | hwint_master 0 170 | 171 | ALIGN 16 172 | hwint01: ; Interrupt routine for irq 1 (keyboard) 173 | hwint_master 1 174 | 175 | ALIGN 16 176 | hwint02: ; Interrupt routine for irq 2 (cascade!) 177 | hwint_master 2 178 | 179 | ALIGN 16 180 | hwint03: ; Interrupt routine for irq 3 (second serial) 181 | hwint_master 3 182 | 183 | ALIGN 16 184 | hwint04: ; Interrupt routine for irq 4 (first serial) 185 | hwint_master 4 186 | 187 | ALIGN 16 188 | hwint05: ; Interrupt routine for irq 5 (XT winchester) 189 | hwint_master 5 190 | 191 | ALIGN 16 192 | hwint06: ; Interrupt routine for irq 6 (floppy) 193 | hwint_master 6 194 | 195 | ALIGN 16 196 | hwint07: ; Interrupt routine for irq 7 (printer) 197 | hwint_master 7 198 | 199 | ; --------------------------------- 200 | %macro hwint_slave 1 201 | call save 202 | in al, INT_S_CTLMASK ; `. 203 | or al, (1 << (%1 - 8)) ; | 屏蔽当前中断 204 | out INT_S_CTLMASK, al ; / 205 | mov al, EOI ; `. 置EOI位(master) 206 | out INT_M_CTL, al ; / 207 | nop ; `. 置EOI位(slave) 208 | out INT_S_CTL, al ; / 一定注意:slave和master都要置EOI 209 | sti ; CPU在响应中断的过程中会自动关中断,这句之后就允许响应新的中断 210 | push %1 ; `. 211 | call [irq_table + 4 * %1] ; | 中断处理程序 212 | pop ecx ; / 213 | cli 214 | in al, INT_S_CTLMASK ; `. 215 | and al, ~(1 << (%1 - 8)) ; | 恢复接受当前中断 216 | out INT_S_CTLMASK, al ; / 217 | ret 218 | %endmacro 219 | ; --------------------------------- 220 | 221 | ALIGN 16 222 | hwint08: ; Interrupt routine for irq 8 (realtime clock). 223 | hwint_slave 8 224 | 225 | ALIGN 16 226 | hwint09: ; Interrupt routine for irq 9 (irq 2 redirected) 227 | hwint_slave 9 228 | 229 | ALIGN 16 230 | hwint10: ; Interrupt routine for irq 10 231 | hwint_slave 10 232 | 233 | ALIGN 16 234 | hwint11: ; Interrupt routine for irq 11 235 | hwint_slave 11 236 | 237 | ALIGN 16 238 | hwint12: ; Interrupt routine for irq 12 239 | hwint_slave 12 240 | 241 | ALIGN 16 242 | hwint13: ; Interrupt routine for irq 13 (FPU exception) 243 | hwint_slave 13 244 | 245 | ALIGN 16 246 | hwint14: ; Interrupt routine for irq 14 (AT winchester) 247 | hwint_slave 14 248 | 249 | ALIGN 16 250 | hwint15: ; Interrupt routine for irq 15 251 | hwint_slave 15 252 | 253 | 254 | 255 | ; 中断和异常 -- 异常 256 | divide_error: 257 | push 0xFFFFFFFF ; no err code 258 | push 0 ; vector_no = 0 259 | jmp exception 260 | single_step_exception: 261 | push 0xFFFFFFFF ; no err code 262 | push 1 ; vector_no = 1 263 | jmp exception 264 | nmi: 265 | push 0xFFFFFFFF ; no err code 266 | push 2 ; vector_no = 2 267 | jmp exception 268 | breakpoint_exception: 269 | push 0xFFFFFFFF ; no err code 270 | push 3 ; vector_no = 3 271 | jmp exception 272 | overflow: 273 | push 0xFFFFFFFF ; no err code 274 | push 4 ; vector_no = 4 275 | jmp exception 276 | bounds_check: 277 | push 0xFFFFFFFF ; no err code 278 | push 5 ; vector_no = 5 279 | jmp exception 280 | inval_opcode: 281 | push 0xFFFFFFFF ; no err code 282 | push 6 ; vector_no = 6 283 | jmp exception 284 | copr_not_available: 285 | push 0xFFFFFFFF ; no err code 286 | push 7 ; vector_no = 7 287 | jmp exception 288 | double_fault: 289 | push 8 ; vector_no = 8 290 | jmp exception 291 | copr_seg_overrun: 292 | push 0xFFFFFFFF ; no err code 293 | push 9 ; vector_no = 9 294 | jmp exception 295 | inval_tss: 296 | push 10 ; vector_no = A 297 | jmp exception 298 | segment_not_present: 299 | push 11 ; vector_no = B 300 | jmp exception 301 | stack_exception: 302 | push 12 ; vector_no = C 303 | jmp exception 304 | general_protection: 305 | push 13 ; vector_no = D 306 | jmp exception 307 | page_fault: 308 | push 14 ; vector_no = E 309 | jmp exception 310 | copr_error: 311 | push 0xFFFFFFFF ; no err code 312 | push 16 ; vector_no = 10h 313 | jmp exception 314 | 315 | exception: 316 | call exception_handler 317 | add esp, 4*2 ; 让栈顶指向 EIP,堆栈中从顶向下依次是:EIP、CS、EFLAGS 318 | hlt 319 | 320 | ; ============================================================================= 321 | ; save 322 | ; ============================================================================= 323 | save: 324 | pushad ; `. 325 | push ds ; | 326 | push es ; | 保存原寄存器值 327 | push fs ; | 328 | push gs ; / 329 | 330 | ;; 注意,从这里开始,一直到 `mov esp, StackTop',中间坚决不能用 push/pop 指令, 331 | ;; 因为当前 esp 指向 proc_table 里的某个位置,push 会破坏掉进程表,导致灾难性后果! 332 | 333 | mov esi, edx ; 保存 edx,因为 edx 里保存了系统调用的参数 334 | ;(没用栈,而是用了另一个寄存器 esi) 335 | mov dx, ss 336 | mov ds, dx 337 | mov es, dx 338 | mov fs, dx 339 | 340 | mov edx, esi ; 恢复 edx 341 | 342 | mov esi, esp ;esi = 进程表起始地址 343 | 344 | inc dword [k_reenter] ;k_reenter++; 345 | cmp dword [k_reenter], 0 ;if(k_reenter ==0) 346 | jne .1 ;{ 347 | mov esp, StackTop ; mov esp, StackTop <--切换到内核栈 348 | push restart ; push restart 349 | jmp [esi + RETADR - P_STACKBASE]; return; 350 | .1: ;} else { 已经在内核栈,不需要再切换 351 | push restart_reenter ; push restart_reenter 352 | jmp [esi + RETADR - P_STACKBASE]; return; 353 | ;} 354 | 355 | 356 | ; ============================================================================= 357 | ; sys_call 358 | ; ============================================================================= 359 | sys_call: 360 | call save 361 | 362 | sti 363 | push esi 364 | 365 | push dword [p_proc_ready] 366 | push edx 367 | push ecx 368 | push ebx 369 | call [sys_call_table + eax * 4] 370 | add esp, 4 * 4 371 | 372 | pop esi 373 | mov [esi + EAXREG - P_STACKBASE], eax 374 | cli 375 | 376 | ret 377 | 378 | 379 | ; ==================================================================================== 380 | ; restart 381 | ; ==================================================================================== 382 | restart: 383 | mov esp, [p_proc_ready] 384 | lldt [esp + P_LDT_SEL] 385 | lea eax, [esp + P_STACKTOP] 386 | mov dword [tss + TSS3_S_SP0], eax 387 | restart_reenter: 388 | dec dword [k_reenter] 389 | pop gs 390 | pop fs 391 | pop es 392 | pop ds 393 | popad 394 | add esp, 4 395 | iretd 396 | 397 | -------------------------------------------------------------------------------- /NanoCore/keyboard.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "keymap.h" 15 | #include "proto.h" 16 | 17 | PRIVATE struct kb_inbuf kb_in; 18 | PRIVATE int code_with_E0; 19 | PRIVATE int shift_l; /* l shift state */ 20 | PRIVATE int shift_r; /* r shift state */ 21 | PRIVATE int alt_l; /* l alt state */ 22 | PRIVATE int alt_r; /* r left state */ 23 | PRIVATE int ctrl_l; /* l ctrl state */ 24 | PRIVATE int ctrl_r; /* l ctrl state */ 25 | PRIVATE int caps_lock; /* Caps Lock */ 26 | PRIVATE int num_lock; /* Num Lock */ 27 | PRIVATE int scroll_lock; /* Scroll Lock */ 28 | PRIVATE int column; 29 | 30 | PRIVATE u8 get_byte_from_kb_buf(); 31 | PRIVATE void set_leds(); 32 | PRIVATE void kb_wait(); 33 | PRIVATE void kb_ack(); 34 | 35 | 36 | /***************************************************************************** 37 | * keyboard_handler 38 | *****************************************************************************/ 39 | /** 40 | * Handles the interrupts generated by the keyboard controller. 41 | * 42 | * @param irq The IRQ corresponding to the keyboard, unused here. 43 | *****************************************************************************/ 44 | PUBLIC void keyboard_handler(int irq) 45 | { 46 | u8 scan_code = in_byte(KB_DATA); 47 | 48 | if (kb_in.count < KB_IN_BYTES) { 49 | *(kb_in.p_head) = scan_code; 50 | kb_in.p_head++; 51 | if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) 52 | kb_in.p_head = kb_in.buf; 53 | kb_in.count++; 54 | } 55 | 56 | key_pressed = 1; 57 | } 58 | 59 | 60 | /***************************************************************************** 61 | * init_keyboard 62 | *****************************************************************************/ 63 | /** 64 | * Initialize some variables and set keyboard interrupt handler. 65 | * 66 | *****************************************************************************/ 67 | PUBLIC void init_keyboard() 68 | { 69 | kb_in.count = 0; 70 | kb_in.p_head = kb_in.p_tail = kb_in.buf; 71 | 72 | shift_l = shift_r = 0; 73 | alt_l = alt_r = 0; 74 | ctrl_l = ctrl_r = 0; 75 | 76 | caps_lock = 0; 77 | num_lock = 1; 78 | scroll_lock = 0; 79 | 80 | column = 0; 81 | 82 | set_leds(); 83 | 84 | put_irq_handler(KEYBOARD_IRQ, keyboard_handler); 85 | enable_irq(KEYBOARD_IRQ); 86 | } 87 | 88 | 89 | /***************************************************************************** 90 | * keyboard_read 91 | *****************************************************************************/ 92 | /** 93 | * Yes, it is an ugly function. 94 | * 95 | * @param tty Which TTY is reading the keyboard input. 96 | *****************************************************************************/ 97 | PUBLIC void keyboard_read(TTY* tty) 98 | { 99 | u8 scan_code; 100 | 101 | /** 102 | * 1 : make 103 | * 0 : break 104 | */ 105 | int make; 106 | 107 | /** 108 | * We use a integer to record a key press. 109 | * For instance, if the key HOME is pressed, key will be evaluated to 110 | * `HOME' defined in keyboard.h. 111 | */ 112 | u32 key = 0; 113 | 114 | 115 | /** 116 | * This var points to a row in keymap[]. I don't use two-dimension 117 | * array because I don't like it. 118 | */ 119 | u32* keyrow; 120 | 121 | while (kb_in.count > 0) { 122 | code_with_E0 = 0; 123 | scan_code = get_byte_from_kb_buf(); 124 | 125 | /* parse the scan code below */ 126 | if (scan_code == 0xE1) { 127 | int i; 128 | u8 pausebreak_scan_code[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5}; 129 | int is_pausebreak = 1; 130 | for (i = 1; i < 6; i++) { 131 | if (get_byte_from_kb_buf() != pausebreak_scan_code[i]) { 132 | is_pausebreak = 0; 133 | break; 134 | } 135 | } 136 | if (is_pausebreak) { 137 | key = PAUSEBREAK; 138 | } 139 | } 140 | else if (scan_code == 0xE0) { 141 | code_with_E0 = 1; 142 | scan_code = get_byte_from_kb_buf(); 143 | 144 | /* PrintScreen is pressed */ 145 | if (scan_code == 0x2A) { 146 | code_with_E0 = 0; 147 | if ((scan_code = get_byte_from_kb_buf()) == 0xE0) { 148 | code_with_E0 = 1; 149 | if ((scan_code = get_byte_from_kb_buf()) == 0x37) { 150 | key = PRINTSCREEN; 151 | make = 1; 152 | } 153 | } 154 | } 155 | /* PrintScreen is released */ 156 | else if (scan_code == 0xB7) { 157 | code_with_E0 = 0; 158 | if ((scan_code = get_byte_from_kb_buf()) == 0xE0) { 159 | code_with_E0 = 1; 160 | if ((scan_code = get_byte_from_kb_buf()) == 0xAA) { 161 | key = PRINTSCREEN; 162 | make = 0; 163 | } 164 | } 165 | } 166 | } 167 | 168 | if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) { 169 | int caps; 170 | 171 | /* make or break */ 172 | make = (scan_code & FLAG_BREAK ? 0 : 1); 173 | 174 | keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS]; 175 | 176 | column = 0; 177 | 178 | caps = shift_l || shift_r; 179 | if (caps_lock && 180 | keyrow[0] >= 'a' && keyrow[0] <= 'z') 181 | caps = !caps; 182 | 183 | if (caps) 184 | column = 1; 185 | 186 | if (code_with_E0) 187 | column = 2; 188 | 189 | key = keyrow[column]; 190 | 191 | switch(key) { 192 | case SHIFT_L: 193 | shift_l = make; 194 | break; 195 | case SHIFT_R: 196 | shift_r = make; 197 | break; 198 | case CTRL_L: 199 | ctrl_l = make; 200 | break; 201 | case CTRL_R: 202 | ctrl_r = make; 203 | break; 204 | case ALT_L: 205 | alt_l = make; 206 | break; 207 | case ALT_R: 208 | alt_l = make; 209 | break; 210 | case CAPS_LOCK: 211 | if (make) { 212 | caps_lock = !caps_lock; 213 | set_leds(); 214 | } 215 | break; 216 | case NUM_LOCK: 217 | if (make) { 218 | num_lock = !num_lock; 219 | set_leds(); 220 | } 221 | break; 222 | case SCROLL_LOCK: 223 | if (make) { 224 | scroll_lock = !scroll_lock; 225 | set_leds(); 226 | } 227 | break; 228 | default: 229 | break; 230 | } 231 | } 232 | 233 | if(make){ /* Break Code is ignored */ 234 | int pad = 0; 235 | 236 | /* deal with the numpad first */ 237 | if ((key >= PAD_SLASH) && (key <= PAD_9)) { 238 | pad = 1; 239 | switch(key) { /* '/', '*', '-', '+', 240 | * and 'Enter' in num pad 241 | */ 242 | case PAD_SLASH: 243 | key = '/'; 244 | break; 245 | case PAD_STAR: 246 | key = '*'; 247 | break; 248 | case PAD_MINUS: 249 | key = '-'; 250 | break; 251 | case PAD_PLUS: 252 | key = '+'; 253 | break; 254 | case PAD_ENTER: 255 | key = ENTER; 256 | break; 257 | default: 258 | /* the value of these keys 259 | * depends on the Numlock 260 | */ 261 | if (num_lock) { /* '0' ~ '9' and '.' in num pad */ 262 | if (key >= PAD_0 && key <= PAD_9) 263 | key = key - PAD_0 + '0'; 264 | else if (key == PAD_DOT) 265 | key = '.'; 266 | } 267 | else{ 268 | switch(key) { 269 | case PAD_HOME: 270 | key = HOME; 271 | break; 272 | case PAD_END: 273 | key = END; 274 | break; 275 | case PAD_PAGEUP: 276 | key = PAGEUP; 277 | break; 278 | case PAD_PAGEDOWN: 279 | key = PAGEDOWN; 280 | break; 281 | case PAD_INS: 282 | key = INSERT; 283 | break; 284 | case PAD_UP: 285 | key = UP; 286 | break; 287 | case PAD_DOWN: 288 | key = DOWN; 289 | break; 290 | case PAD_LEFT: 291 | key = LEFT; 292 | break; 293 | case PAD_RIGHT: 294 | key = RIGHT; 295 | break; 296 | case PAD_DOT: 297 | key = DELETE; 298 | break; 299 | default: 300 | break; 301 | } 302 | } 303 | break; 304 | } 305 | } 306 | key |= shift_l ? FLAG_SHIFT_L : 0; 307 | key |= shift_r ? FLAG_SHIFT_R : 0; 308 | key |= ctrl_l ? FLAG_CTRL_L : 0; 309 | key |= ctrl_r ? FLAG_CTRL_R : 0; 310 | key |= alt_l ? FLAG_ALT_L : 0; 311 | key |= alt_r ? FLAG_ALT_R : 0; 312 | key |= pad ? FLAG_PAD : 0; 313 | 314 | in_process(tty, key); 315 | } 316 | } 317 | } 318 | 319 | 320 | /***************************************************************************** 321 | * get_byte_from_kb_buf 322 | *****************************************************************************/ 323 | /** 324 | * Read a byte from the keyboard buffer. 325 | * 326 | * @return The byte read. 327 | *****************************************************************************/ 328 | PRIVATE u8 get_byte_from_kb_buf() 329 | { 330 | u8 scan_code; 331 | 332 | while (kb_in.count <= 0) {} /* wait for a byte to arrive */ 333 | 334 | disable_int(); /* for synchronization */ 335 | scan_code = *(kb_in.p_tail); 336 | kb_in.p_tail++; 337 | if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) { 338 | kb_in.p_tail = kb_in.buf; 339 | } 340 | kb_in.count--; 341 | enable_int(); /* for synchronization */ 342 | 343 | return scan_code; 344 | } 345 | 346 | 347 | /***************************************************************************** 348 | * kb_wait 349 | *****************************************************************************/ 350 | /** 351 | * Wait until the input buffer of 8042 is empty. 352 | * 353 | *****************************************************************************/ 354 | PRIVATE void kb_wait() /* 等待 8042 的输入缓冲区空 */ 355 | { 356 | u8 kb_stat; 357 | 358 | do { 359 | kb_stat = in_byte(KB_CMD); 360 | } while (kb_stat & 0x02); 361 | } 362 | 363 | 364 | /***************************************************************************** 365 | * kb_ack 366 | *****************************************************************************/ 367 | /** 368 | * Read from the keyboard controller until a KB_ACK is received. 369 | * 370 | *****************************************************************************/ 371 | PRIVATE void kb_ack() 372 | { 373 | u8 kb_read; 374 | 375 | do { 376 | kb_read = in_byte(KB_DATA); 377 | } while (kb_read != KB_ACK); 378 | } 379 | 380 | 381 | /***************************************************************************** 382 | * set_leds 383 | *****************************************************************************/ 384 | /** 385 | * Set the leds according to: caps_lock, num_lock & scroll_lock. 386 | * 387 | *****************************************************************************/ 388 | PRIVATE void set_leds() 389 | { 390 | u8 leds = (caps_lock << 2) | (num_lock << 1) | scroll_lock; 391 | 392 | kb_wait(); 393 | out_byte(KB_DATA, LED_CODE); 394 | kb_ack(); 395 | 396 | kb_wait(); 397 | out_byte(KB_DATA, leds); 398 | kb_ack(); 399 | } 400 | 401 | -------------------------------------------------------------------------------- /NanoCore/klib.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "config.h" 5 | #include "stdio.h" 6 | #include "const.h" 7 | #include "protect.h" 8 | #include "string.h" 9 | #include "fs.h" 10 | #include "proc.h" 11 | #include "tty.h" 12 | #include "console.h" 13 | #include "global.h" 14 | #include "proto.h" 15 | 16 | 17 | #include "elf.h" 18 | 19 | 20 | /***************************************************************************** 21 | * get_boot_params 22 | *****************************************************************************/ 23 | /** 24 | * The boot parameters have been saved by LOADER. 25 | * We just read them out. 26 | * 27 | * @param pbp Ptr to the boot params structure 28 | *****************************************************************************/ 29 | PUBLIC void get_boot_params(struct boot_params * pbp) 30 | { 31 | /** 32 | * Boot params should have been saved at BOOT_PARAM_ADDR. 33 | * @see include/load.inc boot/loader.asm boot/hdloader.asm 34 | */ 35 | int * p = (int*)BOOT_PARAM_ADDR; 36 | assert(p[BI_MAG] == BOOT_PARAM_MAGIC); 37 | 38 | pbp->mem_size = p[BI_MEM_SIZE]; 39 | pbp->kernel_file = (unsigned char *)(p[BI_KERNEL_FILE]); 40 | 41 | /** 42 | * the kernel file should be a ELF executable, 43 | * check it's magic number 44 | */ 45 | assert(memcmp(pbp->kernel_file, ELFMAG, SELFMAG) == 0); 46 | } 47 | 48 | 49 | /***************************************************************************** 50 | * get_kernel_map 51 | *****************************************************************************/ 52 | /** 53 | * Parse the kernel file, get the memory range of the kernel image. 54 | * 55 | * - The meaning of `base': base => first_valid_byte 56 | * - The meaning of `limit': base + limit => last_valid_byte 57 | * 58 | * @param b Memory base of kernel. 59 | * @param l Memory limit of kernel. 60 | *****************************************************************************/ 61 | PUBLIC int get_kernel_map(unsigned int * b, unsigned int * l) 62 | { 63 | struct boot_params bp; 64 | get_boot_params(&bp); 65 | 66 | Elf32_Ehdr* elf_header = (Elf32_Ehdr*)(bp.kernel_file); 67 | 68 | /* the kernel file should be in ELF format */ 69 | if (memcmp(elf_header->e_ident, ELFMAG, SELFMAG) != 0) 70 | return -1; 71 | 72 | *b = ~0; 73 | unsigned int t = 0; 74 | int i; 75 | for (i = 0; i < elf_header->e_shnum; i++) { 76 | Elf32_Shdr* section_header = 77 | (Elf32_Shdr*)(bp.kernel_file + 78 | elf_header->e_shoff + 79 | i * elf_header->e_shentsize); 80 | if (section_header->sh_flags & SHF_ALLOC) { 81 | int bottom = section_header->sh_addr; 82 | int top = section_header->sh_addr + 83 | section_header->sh_size; 84 | 85 | if (*b > bottom) 86 | *b = bottom; 87 | if (t < top) 88 | t = top; 89 | } 90 | } 91 | assert(*b < t); 92 | *l = t - *b - 1; 93 | 94 | return 0; 95 | } 96 | 97 | /*======================================================================* 98 | itoa 99 | *======================================================================*/ 100 | PUBLIC char * itoa(char * str, int num)/* 数字前面的 0 不被显示出来, 比如 0000B800 被显示成 B800 */ 101 | { 102 | char * p = str; 103 | char ch; 104 | int i; 105 | int flag = 0; 106 | 107 | *p++ = '0'; 108 | *p++ = 'x'; 109 | 110 | if(num == 0){ 111 | *p++ = '0'; 112 | } 113 | else{ 114 | for(i=28;i>=0;i-=4){ 115 | ch = (num >> i) & 0xF; 116 | if(flag || (ch > 0)){ 117 | flag = 1; 118 | ch += '0'; 119 | if(ch > '9'){ 120 | ch += 7; 121 | } 122 | *p++ = ch; 123 | } 124 | } 125 | } 126 | 127 | *p = 0; 128 | 129 | return str; 130 | } 131 | 132 | 133 | /*======================================================================* 134 | disp_int 135 | *======================================================================*/ 136 | PUBLIC void disp_int(int input) 137 | { 138 | char output[16]; 139 | itoa(output, input); 140 | disp_str(output); 141 | } 142 | 143 | /*======================================================================* 144 | delay 145 | *======================================================================*/ 146 | PUBLIC void delay(int time) 147 | { 148 | int i, j, k; 149 | for(k=0;k= 8 at the slave 8259 168 | disable_0: 169 | in al, INT_M_CTLMASK 170 | test al, ah 171 | jnz dis_already ; already disabled? 172 | or al, ah 173 | out INT_M_CTLMASK, al ; set bit at master 8259 174 | popf 175 | mov eax, 1 ; disabled by this function 176 | ret 177 | disable_8: 178 | in al, INT_S_CTLMASK 179 | test al, ah 180 | jnz dis_already ; already disabled? 181 | or al, ah 182 | out INT_S_CTLMASK, al ; set bit at slave 8259 183 | popf 184 | mov eax, 1 ; disabled by this function 185 | ret 186 | dis_already: 187 | popf 188 | xor eax, eax ; already disabled 189 | ret 190 | 191 | ; ======================================================================== 192 | ; void enable_irq(int irq); 193 | ; ======================================================================== 194 | ; Enable an interrupt request line by clearing an 8259 bit. 195 | ; Equivalent code: 196 | ; if(irq < 8){ 197 | ; out_byte(INT_M_CTLMASK, in_byte(INT_M_CTLMASK) & ~(1 << irq)); 198 | ; } 199 | ; else{ 200 | ; out_byte(INT_S_CTLMASK, in_byte(INT_S_CTLMASK) & ~(1 << irq)); 201 | ; } 202 | ; 203 | enable_irq: 204 | mov ecx, [esp + 4] ; irq 205 | pushf 206 | cli 207 | mov ah, ~1 208 | rol ah, cl ; ah = ~(1 << (irq % 8)) 209 | cmp cl, 8 210 | jae enable_8 ; enable irq >= 8 at the slave 8259 211 | enable_0: 212 | in al, INT_M_CTLMASK 213 | and al, ah 214 | out INT_M_CTLMASK, al ; clear bit at master 8259 215 | popf 216 | ret 217 | enable_8: 218 | in al, INT_S_CTLMASK 219 | and al, ah 220 | out INT_S_CTLMASK, al ; clear bit at slave 8259 221 | popf 222 | ret 223 | 224 | ; ======================================================================== 225 | ; void disable_int(); 226 | ; ======================================================================== 227 | disable_int: 228 | cli 229 | ret 230 | 231 | ; ======================================================================== 232 | ; void enable_int(); 233 | ; ======================================================================== 234 | enable_int: 235 | sti 236 | ret 237 | 238 | ; ======================================================================== 239 | ; void glitter(int row, int col); 240 | ; ======================================================================== 241 | glitter: 242 | push eax 243 | push ebx 244 | push edx 245 | 246 | mov eax, [.current_char] 247 | inc eax 248 | cmp eax, .strlen 249 | je .1 250 | jmp .2 251 | .1: 252 | xor eax, eax 253 | .2: 254 | mov [.current_char], eax 255 | mov dl, byte [eax + .glitter_str] 256 | 257 | xor eax, eax 258 | mov al, [esp + 16] ; row 259 | mov bl, .line_width 260 | mul bl ; ax <- row * 80 261 | mov bx, [esp + 20] ; col 262 | add ax, bx 263 | shl ax, 1 264 | movzx eax, ax 265 | 266 | mov [gs:eax], dl 267 | 268 | inc eax 269 | mov byte [gs:eax], 4 270 | 271 | jmp .end 272 | 273 | .current_char: dd 0 274 | .glitter_str: db '-\|/' 275 | db '1234567890' 276 | db 'abcdefghijklmnopqrstuvwxyz' 277 | db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 278 | .strlen equ $ - .glitter_str 279 | .line_width equ 80 280 | 281 | .end: 282 | pop edx 283 | pop ebx 284 | pop eax 285 | ret 286 | 287 | 288 | -------------------------------------------------------------------------------- /NanoCore/main.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * kernel_main 18 | *****************************************************************************/ 19 | /** 20 | * jmp from kernel.asm::_start. 21 | * 22 | *****************************************************************************/ 23 | PUBLIC int kernel_main() 24 | { 25 | disp_str("\n###################### NanoCore Running ######################\n"); 26 | 27 | int i, j, eflags, prio; 28 | u8 rpl; 29 | u8 priv; /* privilege */ 30 | 31 | struct task * t; 32 | struct proc * p = proc_table; 33 | 34 | char * stk = task_stack + STACK_SIZE_TOTAL; 35 | 36 | for (i = 0; i < NR_TASKS + NR_PROCS; i++,p++,t++) { 37 | if (i >= NR_TASKS + NR_NATIVE_PROCS) { 38 | p->p_flags = FREE_SLOT; 39 | continue; 40 | } 41 | 42 | if (i < NR_TASKS) { /* TASK */ 43 | t = task_table + i; 44 | priv = PRIVILEGE_TASK; 45 | rpl = RPL_TASK; 46 | eflags = 0x1202;/* IF=1, IOPL=1, bit 2 is always 1 */ 47 | prio = 15; 48 | } 49 | else { /* USER PROC */ 50 | t = user_proc_table + (i - NR_TASKS); 51 | priv = PRIVILEGE_USER; 52 | rpl = RPL_USER; 53 | eflags = 0x202; /* IF=1, bit 2 is always 1 */ 54 | prio = 5; 55 | } 56 | 57 | strcpy(p->name, t->name); /* name of the process */ 58 | p->p_parent = NO_TASK; 59 | 60 | if (strcmp(t->name, "INIT") != 0) { 61 | p->ldts[INDEX_LDT_C] = gdt[SELECTOR_KERNEL_CS >> 3]; 62 | p->ldts[INDEX_LDT_RW] = gdt[SELECTOR_KERNEL_DS >> 3]; 63 | 64 | /* change the DPLs */ 65 | p->ldts[INDEX_LDT_C].attr1 = DA_C | priv << 5; 66 | p->ldts[INDEX_LDT_RW].attr1 = DA_DRW | priv << 5; 67 | } 68 | else { /* INIT process */ 69 | unsigned int k_base; 70 | unsigned int k_limit; 71 | int ret = get_kernel_map(&k_base, &k_limit); 72 | assert(ret == 0); 73 | init_desc(&p->ldts[INDEX_LDT_C], 74 | 0, /* bytes before the entry point 75 | * are useless (wasted) for the 76 | * INIT process, doesn't matter 77 | */ 78 | (k_base + k_limit) >> LIMIT_4K_SHIFT, 79 | DA_32 | DA_LIMIT_4K | DA_C | priv << 5); 80 | 81 | init_desc(&p->ldts[INDEX_LDT_RW], 82 | 0, /* bytes before the entry point 83 | * are useless (wasted) for the 84 | * INIT process, doesn't matter 85 | */ 86 | (k_base + k_limit) >> LIMIT_4K_SHIFT, 87 | DA_32 | DA_LIMIT_4K | DA_DRW | priv << 5); 88 | } 89 | 90 | p->regs.cs = INDEX_LDT_C << 3 | SA_TIL | rpl; 91 | p->regs.ds = 92 | p->regs.es = 93 | p->regs.fs = 94 | p->regs.ss = INDEX_LDT_RW << 3 | SA_TIL | rpl; 95 | p->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl; 96 | p->regs.eip = (u32)t->initial_eip; 97 | p->regs.esp = (u32)stk; 98 | p->regs.eflags = eflags; 99 | 100 | p->ticks = p->priority = prio; 101 | 102 | p->p_flags = 0; 103 | p->p_msg = 0; 104 | p->p_recvfrom = NO_TASK; 105 | p->p_sendto = NO_TASK; 106 | p->has_int_msg = 0; 107 | p->q_sending = 0; 108 | p->next_sending = 0; 109 | 110 | for (j = 0; j < NR_FILES; j++) 111 | p->filp[j] = 0; 112 | 113 | stk -= t->stacksize; 114 | } 115 | 116 | k_reenter = 0; 117 | ticks = 0; 118 | 119 | p_proc_ready = proc_table; 120 | 121 | init_clock(); 122 | init_keyboard(); 123 | 124 | restart(); 125 | 126 | while(1){} 127 | } 128 | 129 | 130 | /***************************************************************************** 131 | * get_ticks 132 | *****************************************************************************/ 133 | PUBLIC int get_ticks() 134 | { 135 | MESSAGE msg; 136 | reset_msg(&msg); 137 | msg.type = GET_TICKS; 138 | send_recv(BOTH, TASK_SYS, &msg); 139 | return msg.RETVAL; 140 | } 141 | 142 | 143 | /** 144 | * @struct posix_tar_header 145 | * Borrowed from GNU `tar' 146 | */ 147 | struct posix_tar_header 148 | { /* byte offset */ 149 | char name[100]; /* 0 */ 150 | char mode[8]; /* 100 */ 151 | char uid[8]; /* 108 */ 152 | char gid[8]; /* 116 */ 153 | char size[12]; /* 124 */ 154 | char mtime[12]; /* 136 */ 155 | char chksum[8]; /* 148 */ 156 | char typeflag; /* 156 */ 157 | char linkname[100]; /* 157 */ 158 | char magic[6]; /* 257 */ 159 | char version[2]; /* 263 */ 160 | char uname[32]; /* 265 */ 161 | char gname[32]; /* 297 */ 162 | char devmajor[8]; /* 329 */ 163 | char devminor[8]; /* 337 */ 164 | char prefix[155]; /* 345 */ 165 | /* 500 */ 166 | }; 167 | 168 | /***************************************************************************** 169 | * untar 170 | *****************************************************************************/ 171 | /** 172 | * Extract the tar file and store them. 173 | * 174 | * @param filename The tar file. 175 | *****************************************************************************/ 176 | void untar(const char * filename) 177 | { 178 | printf("[INFO]Extract: ##########`%s'\n", filename); 179 | int fd = open(filename, O_RDWR); 180 | assert(fd != -1); 181 | 182 | char buf[SECTOR_SIZE * 16]; 183 | int chunk = sizeof(buf); 184 | 185 | while (1) { 186 | read(fd, buf, SECTOR_SIZE); 187 | if (buf[0] == 0) 188 | break; 189 | 190 | struct posix_tar_header * phdr = (struct posix_tar_header *)buf; 191 | char * p = phdr->size; 192 | int f_len = 0; 193 | while (*p) 194 | f_len = (f_len * 8) + (*p++ - '0'); /* octal */ 195 | 196 | int bytes_left = f_len; 197 | int fdout = open(phdr->name, O_CREAT | O_RDWR); 198 | if (fdout == -1) { 199 | printf("[ERRO]failed to extract file: %s\n", phdr->name); 200 | printf("[INFO]Aborted.##########\n"); 201 | return; 202 | } 203 | printf(" %s (%d bytes)\n", phdr->name, f_len); 204 | while (bytes_left) { 205 | int iobytes = min(chunk, bytes_left); 206 | read(fd, buf, 207 | ((iobytes - 1) / SECTOR_SIZE + 1) * SECTOR_SIZE); 208 | write(fdout, buf, iobytes); 209 | bytes_left -= iobytes; 210 | } 211 | close(fdout); 212 | } 213 | 214 | close(fd); 215 | 216 | printf("[INFO]Done, %d files extracted.##########\n"); 217 | } 218 | 219 | void shabby_shell(const char * tty_name) 220 | { 221 | int fd_stdin = open(tty_name, O_RDWR); 222 | assert(fd_stdin == 0); 223 | int fd_stdout = open(tty_name, O_RDWR); 224 | assert(fd_stdout == 1); 225 | 226 | char rdbuf[128]; 227 | 228 | while (1) { 229 | write(1, "$ ", 2); 230 | int r = read(0, rdbuf, 70); 231 | rdbuf[r] = 0; 232 | 233 | int argc = 0; 234 | char * argv[PROC_ORIGIN_STACK]; 235 | char * p = rdbuf; 236 | char * s; 237 | int word = 0; 238 | char ch; 239 | do { 240 | ch = *p; 241 | if (*p != ' ' && *p != 0 && !word) { 242 | s = p; 243 | word = 1; 244 | } 245 | if ((*p == ' ' || *p == 0) && word) { 246 | word = 0; 247 | argv[argc++] = s; 248 | *p = 0; 249 | } 250 | p++; 251 | } while(ch); 252 | argv[argc] = 0; 253 | 254 | int fd = open(argv[0], O_RDWR); 255 | if (fd == -1) { 256 | if (rdbuf[0]) { 257 | write(1, "{", 1); 258 | write(1, rdbuf, r); 259 | write(1, "}\n", 2); 260 | } 261 | } 262 | else { 263 | close(fd); 264 | int pid = fork(); 265 | if (pid != 0) { /* parent */ 266 | int s; 267 | wait(&s); 268 | } 269 | else { /* child */ 270 | execv(argv[0], argv); 271 | } 272 | } 273 | } 274 | 275 | close(1); 276 | close(0); 277 | } 278 | 279 | /***************************************************************************** 280 | * Init 281 | *****************************************************************************/ 282 | /** 283 | * The hen. 284 | * 285 | *****************************************************************************/ 286 | void Init() 287 | { 288 | int fd_stdin = open("/dev_tty0", O_RDWR); 289 | assert(fd_stdin == 0); 290 | int fd_stdout = open("/dev_tty0", O_RDWR); 291 | assert(fd_stdout == 1); 292 | 293 | printf("####################### INIT Running #########################\n"); 294 | 295 | /* extract `cmd.tar' */ 296 | untar("/cmd.tar"); 297 | 298 | 299 | char * tty_list[] = {"/dev_tty1", "/dev_tty2"}; 300 | 301 | int i; 302 | for (i = 0; i < sizeof(tty_list) / sizeof(tty_list[0]); i++) { 303 | int pid = fork(); 304 | if (pid != 0) { /* parent process */ 305 | printf("[INFO]Parent is running, child PID:%d\n", pid); 306 | } 307 | else { /* child process */ 308 | printf("[INFO]Child is running, PID:%d\n", getpid()); 309 | close(fd_stdin); 310 | close(fd_stdout); 311 | 312 | shabby_shell(tty_list[i]); 313 | assert(0); 314 | } 315 | } 316 | 317 | while (1) { 318 | int s; 319 | int child = wait(&s); 320 | printf("[WARN]Child (%d) exited with status: %d.\n", child, s); 321 | } 322 | 323 | assert(0); 324 | } 325 | 326 | 327 | /*======================================================================* 328 | TestA 329 | *======================================================================*/ 330 | void TestA() 331 | { 332 | for(;;); 333 | } 334 | 335 | /*======================================================================* 336 | TestB 337 | *======================================================================*/ 338 | void TestB() 339 | { 340 | for(;;); 341 | } 342 | 343 | /*======================================================================* 344 | TestB 345 | *======================================================================*/ 346 | void TestC() 347 | { 348 | for(;;); 349 | } 350 | 351 | /***************************************************************************** 352 | * panic 353 | *****************************************************************************/ 354 | PUBLIC void panic(const char *fmt, ...) 355 | { 356 | int i; 357 | char buf[256]; 358 | 359 | /* 4 is the size of fmt in the stack */ 360 | va_list arg = (va_list)((char*)&fmt + 4); 361 | 362 | i = vsprintf(buf, fmt, arg); 363 | 364 | printl("%c [WARN]!!panic!! %s", MAG_CH_PANIC, buf); 365 | 366 | /* should never arrive here */ 367 | __asm__ __volatile__("ud2"); 368 | } 369 | 370 | -------------------------------------------------------------------------------- /NanoCore/protect.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "fs.h" 8 | #include "tty.h" 9 | #include "console.h" 10 | #include "proc.h" 11 | #include "string.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /* 本文件内函数声明 */ 17 | PRIVATE void init_idt_desc(unsigned char vector, u8 desc_type, int_handler handler, unsigned char privilege); 18 | 19 | 20 | /* 中断处理函数 */ 21 | void divide_error(); 22 | void single_step_exception(); 23 | void nmi(); 24 | void breakpoint_exception(); 25 | void overflow(); 26 | void bounds_check(); 27 | void inval_opcode(); 28 | void copr_not_available(); 29 | void double_fault(); 30 | void copr_seg_overrun(); 31 | void inval_tss(); 32 | void segment_not_present(); 33 | void stack_exception(); 34 | void general_protection(); 35 | void page_fault(); 36 | void copr_error(); 37 | void hwint00(); 38 | void hwint01(); 39 | void hwint02(); 40 | void hwint03(); 41 | void hwint04(); 42 | void hwint05(); 43 | void hwint06(); 44 | void hwint07(); 45 | void hwint08(); 46 | void hwint09(); 47 | void hwint10(); 48 | void hwint11(); 49 | void hwint12(); 50 | void hwint13(); 51 | void hwint14(); 52 | void hwint15(); 53 | 54 | 55 | /*======================================================================* 56 | init_prot 57 | *----------------------------------------------------------------------* 58 | 初始化 IDT 59 | *======================================================================*/ 60 | PUBLIC void init_prot() 61 | { 62 | init_8259A(); 63 | 64 | /* 全部初始化成中断门(没有陷阱门) */ 65 | init_idt_desc(INT_VECTOR_DIVIDE, DA_386IGate, 66 | divide_error, PRIVILEGE_KRNL); 67 | 68 | init_idt_desc(INT_VECTOR_DEBUG, DA_386IGate, 69 | single_step_exception, PRIVILEGE_KRNL); 70 | 71 | init_idt_desc(INT_VECTOR_NMI, DA_386IGate, 72 | nmi, PRIVILEGE_KRNL); 73 | 74 | init_idt_desc(INT_VECTOR_BREAKPOINT, DA_386IGate, 75 | breakpoint_exception, PRIVILEGE_USER); 76 | 77 | init_idt_desc(INT_VECTOR_OVERFLOW, DA_386IGate, 78 | overflow, PRIVILEGE_USER); 79 | 80 | init_idt_desc(INT_VECTOR_BOUNDS, DA_386IGate, 81 | bounds_check, PRIVILEGE_KRNL); 82 | 83 | init_idt_desc(INT_VECTOR_INVAL_OP, DA_386IGate, 84 | inval_opcode, PRIVILEGE_KRNL); 85 | 86 | init_idt_desc(INT_VECTOR_COPROC_NOT, DA_386IGate, 87 | copr_not_available, PRIVILEGE_KRNL); 88 | 89 | init_idt_desc(INT_VECTOR_DOUBLE_FAULT, DA_386IGate, 90 | double_fault, PRIVILEGE_KRNL); 91 | 92 | init_idt_desc(INT_VECTOR_COPROC_SEG, DA_386IGate, 93 | copr_seg_overrun, PRIVILEGE_KRNL); 94 | 95 | init_idt_desc(INT_VECTOR_INVAL_TSS, DA_386IGate, 96 | inval_tss, PRIVILEGE_KRNL); 97 | 98 | init_idt_desc(INT_VECTOR_SEG_NOT, DA_386IGate, 99 | segment_not_present, PRIVILEGE_KRNL); 100 | 101 | init_idt_desc(INT_VECTOR_STACK_FAULT, DA_386IGate, 102 | stack_exception, PRIVILEGE_KRNL); 103 | 104 | init_idt_desc(INT_VECTOR_PROTECTION, DA_386IGate, 105 | general_protection, PRIVILEGE_KRNL); 106 | 107 | init_idt_desc(INT_VECTOR_PAGE_FAULT, DA_386IGate, 108 | page_fault, PRIVILEGE_KRNL); 109 | 110 | init_idt_desc(INT_VECTOR_COPROC_ERR, DA_386IGate, 111 | copr_error, PRIVILEGE_KRNL); 112 | 113 | init_idt_desc(INT_VECTOR_IRQ0 + 0, DA_386IGate, 114 | hwint00, PRIVILEGE_KRNL); 115 | 116 | init_idt_desc(INT_VECTOR_IRQ0 + 1, DA_386IGate, 117 | hwint01, PRIVILEGE_KRNL); 118 | 119 | init_idt_desc(INT_VECTOR_IRQ0 + 2, DA_386IGate, 120 | hwint02, PRIVILEGE_KRNL); 121 | 122 | init_idt_desc(INT_VECTOR_IRQ0 + 3, DA_386IGate, 123 | hwint03, PRIVILEGE_KRNL); 124 | 125 | init_idt_desc(INT_VECTOR_IRQ0 + 4, DA_386IGate, 126 | hwint04, PRIVILEGE_KRNL); 127 | 128 | init_idt_desc(INT_VECTOR_IRQ0 + 5, DA_386IGate, 129 | hwint05, PRIVILEGE_KRNL); 130 | 131 | init_idt_desc(INT_VECTOR_IRQ0 + 6, DA_386IGate, 132 | hwint06, PRIVILEGE_KRNL); 133 | 134 | init_idt_desc(INT_VECTOR_IRQ0 + 7, DA_386IGate, 135 | hwint07, PRIVILEGE_KRNL); 136 | 137 | init_idt_desc(INT_VECTOR_IRQ8 + 0, DA_386IGate, 138 | hwint08, PRIVILEGE_KRNL); 139 | 140 | init_idt_desc(INT_VECTOR_IRQ8 + 1, DA_386IGate, 141 | hwint09, PRIVILEGE_KRNL); 142 | 143 | init_idt_desc(INT_VECTOR_IRQ8 + 2, DA_386IGate, 144 | hwint10, PRIVILEGE_KRNL); 145 | 146 | init_idt_desc(INT_VECTOR_IRQ8 + 3, DA_386IGate, 147 | hwint11, PRIVILEGE_KRNL); 148 | 149 | init_idt_desc(INT_VECTOR_IRQ8 + 4, DA_386IGate, 150 | hwint12, PRIVILEGE_KRNL); 151 | 152 | init_idt_desc(INT_VECTOR_IRQ8 + 5, DA_386IGate, 153 | hwint13, PRIVILEGE_KRNL); 154 | 155 | init_idt_desc(INT_VECTOR_IRQ8 + 6, DA_386IGate, 156 | hwint14, PRIVILEGE_KRNL); 157 | 158 | init_idt_desc(INT_VECTOR_IRQ8 + 7, DA_386IGate, 159 | hwint15, PRIVILEGE_KRNL); 160 | 161 | init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, 162 | sys_call, PRIVILEGE_USER); 163 | 164 | /* Fill the TSS descriptor in GDT */ 165 | memset(&tss, 0, sizeof(tss)); 166 | tss.ss0 = SELECTOR_KERNEL_DS; 167 | init_desc(&gdt[INDEX_TSS], 168 | makelinear(SELECTOR_KERNEL_DS, &tss), 169 | sizeof(tss) - 1, 170 | DA_386TSS); 171 | tss.iobase = sizeof(tss); /* No IO permission bitmap */ 172 | 173 | /* Fill the LDT descriptors of each proc in GDT */ 174 | int i; 175 | for (i = 0; i < NR_TASKS + NR_PROCS; i++) { 176 | memset(&proc_table[i], 0, sizeof(struct proc)); 177 | 178 | proc_table[i].ldt_sel = SELECTOR_LDT_FIRST + (i << 3); 179 | assert(INDEX_LDT_FIRST + i < GDT_SIZE); 180 | init_desc(&gdt[INDEX_LDT_FIRST + i], 181 | makelinear(SELECTOR_KERNEL_DS, proc_table[i].ldts), 182 | LDT_SIZE * sizeof(struct descriptor) - 1, 183 | DA_LDT); 184 | } 185 | } 186 | 187 | 188 | /*======================================================================* 189 | init_idt_desc 190 | *----------------------------------------------------------------------* 191 | 初始化 386 中断门 192 | *======================================================================*/ 193 | PUBLIC void init_idt_desc(unsigned char vector, u8 desc_type, int_handler handler, unsigned char privilege) 194 | { 195 | struct gate * p_gate = &idt[vector]; 196 | u32 base = (u32)handler; 197 | p_gate->offset_low = base & 0xFFFF; 198 | p_gate->selector = SELECTOR_KERNEL_CS; 199 | p_gate->dcount = 0; 200 | p_gate->attr = desc_type | (privilege << 5); 201 | p_gate->offset_high = (base >> 16) & 0xFFFF; 202 | } 203 | 204 | 205 | /*======================================================================* 206 | seg2phys 207 | *----------------------------------------------------------------------* 208 | 由段名求绝对地址 209 | *======================================================================*/ 210 | PUBLIC u32 seg2linear(u16 seg) 211 | { 212 | struct descriptor* p_dest = &gdt[seg >> 3]; 213 | 214 | return (p_dest->base_high << 24) | (p_dest->base_mid << 16) | (p_dest->base_low); 215 | } 216 | 217 | /*======================================================================* 218 | init_descriptor 219 | *----------------------------------------------------------------------* 220 | 初始化段描述符 221 | *======================================================================*/ 222 | PUBLIC void init_desc(struct descriptor * p_desc, u32 base, u32 limit, u16 attribute) 223 | { 224 | p_desc->limit_low = limit & 0x0FFFF; /* 段界限 1 (2 字节) */ 225 | p_desc->base_low = base & 0x0FFFF; /* 段基址 1 (2 字节) */ 226 | p_desc->base_mid = (base >> 16) & 0x0FF; /* 段基址 2 (1 字节) */ 227 | p_desc->attr1 = attribute & 0xFF; /* 属性 1 */ 228 | p_desc->limit_high_attr2= ((limit >> 16) & 0x0F) | 229 | ((attribute >> 8) & 0xF0); /* 段界限 2 + 属性 2 */ 230 | p_desc->base_high = (base >> 24) & 0x0FF; /* 段基址 3 (1 字节) */ 231 | } 232 | 233 | /*======================================================================* 234 | exception_handler 235 | *----------------------------------------------------------------------* 236 | 异常处理 237 | *======================================================================*/ 238 | PUBLIC void exception_handler(int vec_no, int err_code, int eip, int cs, int eflags) 239 | { 240 | int i; 241 | int text_color = 0x74; /* 灰底红字 */ 242 | char err_description[][64] = { "#DE Divide Error", 243 | "#DB RESERVED", 244 | "— NMI Interrupt", 245 | "#BP Breakpoint", 246 | "#OF Overflow", 247 | "#BR BOUND Range Exceeded", 248 | "#UD Invalid Opcode (Undefined Opcode)", 249 | "#NM Device Not Available (No Math Coprocessor)", 250 | "#DF Double Fault", 251 | " Coprocessor Segment Overrun (reserved)", 252 | "#TS Invalid TSS", 253 | "#NP Segment Not Present", 254 | "#SS Stack-Segment Fault", 255 | "#GP General Protection", 256 | "#PF Page Fault", 257 | "— (Intel reserved. Do not use.)", 258 | "#MF x87 FPU Floating-Point Error (Math Fault)", 259 | "#AC Alignment Check", 260 | "#MC Machine Check", 261 | "#XF SIMD Floating-Point Exception" 262 | }; 263 | 264 | /* 通过打印空格的方式清空屏幕的前五行,并把 disp_pos 清零 */ 265 | disp_pos = 0; 266 | for(i=0;i<80*5;i++){ 267 | disp_str(" "); 268 | } 269 | disp_pos = 0; 270 | 271 | disp_color_str("[ERRO][Core]Exception! --> ", text_color); 272 | disp_color_str(err_description[vec_no], text_color); 273 | disp_color_str("\n\n", text_color); 274 | disp_color_str("[ERRO][Core]EFLAGS:", text_color); 275 | disp_int(eflags); 276 | disp_color_str("CS:", text_color); 277 | disp_int(cs); 278 | disp_color_str("[ERRO][Core]EIP:", text_color); 279 | disp_int(eip); 280 | 281 | if(err_code != 0xFFFFFFFF){ 282 | disp_color_str("[ERRO][Core]Error code:", text_color); 283 | disp_int(err_code); 284 | } 285 | } 286 | 287 | -------------------------------------------------------------------------------- /NanoCore/start.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /*======================================================================* 17 | cstart 18 | *======================================================================*/ 19 | PUBLIC void cstart() 20 | { 21 | printfInfoNotReturn(); 22 | disp_str("Boot Loader \n"); 23 | printfInfoNotReturn(); 24 | disp_str("Loader loaded\n"); 25 | printfInfoNotReturn(); 26 | disp_str("NanoOS [Blue] Build 19/12/29 Version 191229.04.null\n"); 27 | 28 | /* 将 LOADER 中的 GDT 复制到新的 GDT 中 */ 29 | memcpy( &gdt, /* New GDT */ 30 | (void*)(*((u32*)(&gdt_ptr[2]))), /* Base of Old GDT */ 31 | *((u16*)(&gdt_ptr[0])) + 1 /* Limit of Old GDT */ 32 | ); 33 | /* gdt_ptr[6] 共 6 个字节:0~15:Limit 16~47:Base。用作 sgdt 以及 lgdt 的参数。 */ 34 | u16* p_gdt_limit = (u16*)(&gdt_ptr[0]); 35 | u32* p_gdt_base = (u32*)(&gdt_ptr[2]); 36 | *p_gdt_limit = GDT_SIZE * sizeof(struct descriptor) - 1; 37 | *p_gdt_base = (u32)&gdt; 38 | 39 | /* idt_ptr[6] 共 6 个字节:0~15:Limit 16~47:Base。用作 sidt 以及 lidt 的参数。 */ 40 | u16* p_idt_limit = (u16*)(&idt_ptr[0]); 41 | u32* p_idt_base = (u32*)(&idt_ptr[2]); 42 | *p_idt_limit = IDT_SIZE * sizeof(struct gate) - 1; 43 | *p_idt_base = (u32)&idt; 44 | 45 | init_prot(); 46 | 47 | printfInfoNotReturn(); 48 | disp_str("NanoOS [Blue] NanoCore (C) 2019 NanoZero | Hanbings 3219065882@qq.com \n"); 49 | printfInfoNotReturn(); 50 | disp_str("NanoCore [Beta] NanoCore Will Be Better \n"); 51 | printfInfoNotReturn(); 52 | disp_str("NanoCore Loading ...\n"); 53 | //显示版本信息 54 | disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 55 | printfInfoNotReturn(); 56 | disp_str("NanoOS [Blue] Build 19/12/29 Version 191229.04.null\n"); 57 | printfWarnNotReturn(); 58 | disp_str("This Version is a Beta Version\n"); 59 | printfInfoNotReturn(); 60 | disp_str("My Github: https://github.com/hanbings/NanoOS\n"); 61 | } 62 | -------------------------------------------------------------------------------- /NanoCore/systask.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | PRIVATE int read_register(char reg_addr); 17 | PRIVATE u32 get_rtc_time(struct time *t); 18 | 19 | /***************************************************************************** 20 | * task_sys 21 | *****************************************************************************/ 22 | /** 23 | * The main loop of TASK SYS. 24 | * 25 | *****************************************************************************/ 26 | PUBLIC void task_sys() 27 | { 28 | MESSAGE msg; 29 | struct time t; 30 | 31 | while (1) { 32 | send_recv(RECEIVE, ANY, &msg); 33 | int src = msg.source; 34 | 35 | switch (msg.type) { 36 | case GET_TICKS: 37 | msg.RETVAL = ticks; 38 | send_recv(SEND, src, &msg); 39 | break; 40 | case GET_PID: 41 | msg.type = SYSCALL_RET; 42 | msg.PID = src; 43 | send_recv(SEND, src, &msg); 44 | break; 45 | case GET_RTC_TIME: 46 | msg.type = SYSCALL_RET; 47 | get_rtc_time(&t); 48 | phys_copy(va2la(src, msg.BUF), 49 | va2la(TASK_SYS, &t), 50 | sizeof(t)); 51 | send_recv(SEND, src, &msg); 52 | break; 53 | default: 54 | panic("[WARN][Core]unknown msg type"); 55 | break; 56 | } 57 | } 58 | } 59 | 60 | 61 | /***************************************************************************** 62 | * get_rtc_time 63 | *****************************************************************************/ 64 | /** 65 | * Get RTC time from the CMOS 66 | * 67 | * @return Zero. 68 | *****************************************************************************/ 69 | PRIVATE u32 get_rtc_time(struct time *t) 70 | { 71 | t->year = read_register(YEAR); 72 | t->month = read_register(MONTH); 73 | t->day = read_register(DAY); 74 | t->hour = read_register(HOUR); 75 | t->minute = read_register(MINUTE); 76 | t->second = read_register(SECOND); 77 | 78 | if ((read_register(CLK_STATUS) & 0x04) == 0) { 79 | /* Convert BCD to binary (default RTC mode) */ 80 | t->year = BCD_TO_DEC(t->year); 81 | t->month = BCD_TO_DEC(t->month); 82 | t->day = BCD_TO_DEC(t->day); 83 | t->hour = BCD_TO_DEC(t->hour); 84 | t->minute = BCD_TO_DEC(t->minute); 85 | t->second = BCD_TO_DEC(t->second); 86 | } 87 | 88 | t->year += 2000; 89 | 90 | return 0; 91 | } 92 | 93 | /***************************************************************************** 94 | * read_register 95 | *****************************************************************************/ 96 | /** 97 | * Read register from CMOS. 98 | * 99 | * @param reg_addr 100 | * 101 | * @return 102 | *****************************************************************************/ 103 | PRIVATE int read_register(char reg_addr) 104 | { 105 | out_byte(CLK_ELE, reg_addr); 106 | return in_byte(CLK_IO); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # NanoOS API Docs 2 | 3 | ## 这是NanoOS的API文档 4 | 5 | ### 欢迎开发者阅读 6 | 7 | > API版本:191229.04 8 | > 9 | > NanoOS适用版本:NanoOS [Blue] Build 19/12/29 Version 191229.04 以及以上 10 | 11 | ![](https://s2.ax1x.com/2019/12/30/lQDoVK.jpg) 12 | 13 | [NanoOS [Blue\] Build 19/12/29 Version 191229.04版本快照]: 14 | 15 | ![](https://s2.ax1x.com/2019/12/29/lKFurQ.png) 16 | 17 | > 本项目Github地址:https://github.com/hanbings/NanoOS 18 | 19 | | 函数名 | 原型 | 20 | | ---------- | ------------------------------------------------------------ | 21 | | sendrec(); | *int* sendrec(*int* function, *int* src_dest, MESSAGE* p_msg); | 22 | | printx(); | *int* printx(*char** str); | 23 | 24 | | 函数名 | 原型 | 25 | | --------- | ---------------------------------------------------------- | 26 | | memcpy(); | void\* memcpy(void\* es:p_dst, void\* ds:p_src, int size); | 27 | | memset(); | void memset(void\* p_dst, char ch, int size); | 28 | | strcpy(); | char* strcpy(*char** dst, const *char** src); | 29 | | strlen(); | *int* strlen(const *char** p_str); | 30 | 31 | | 函数名 | 原型 | 32 | | --------- | ---------------------------------------------------------- | 33 | | open(); | *int* open (const *char* *pathname, *int* flags); | 34 | | read(); | int read (*int* fd, *void* *buf, *int* count); | 35 | | write(); | *int* write (*int* fd, const *void* *buf, *int* count); | 36 | | close(); | *int* close (*int* fd); | 37 | | unlink(); | *int* unlink (const *char* *pathname); | 38 | 39 | | 函数名 | 原型 | 40 | | ------- | ------------------------------- | 41 | | fork(); | *int* fork (); | 42 | | exit(); | *void* exit (*int* status); | 43 | | wait(); | *int* wait (*int* * status); | 44 | 45 | | 函数名 | 原型 | 46 | | --------- | --------------- | 47 | | getpid(); | *int* getpid(); | 48 | 49 | | 函数名 | 原型 | 50 | | ----------- | ------------------------------------------------------------ | 51 | | printf(); | *int* printf(const *char* *fmt, ...); | 52 | | vsprintf(); | *int* vsprintf(*char* *buf, const *char* *fmt, va_list args); | 53 | | spin(); | *void* spin(*char* * func_name); | 54 | 55 | 示例程序:(Linux中的echo,这是简化版本) 56 | 57 | ```c 58 | #include "stdio.h" 59 | int main(int argc, char* argv[]) 60 | { 61 | int i; 62 | for (i = 1; i < argc; i++) 63 | printf("%s%s", i == 1 ? "" : " ", argv[i]); 64 | printf("\n"); 65 | return 0; 66 | } 67 | ``` 68 | 69 | ``` 70 | $echo Hello World 71 | Hello World 72 | ``` 73 | 74 | 示例编译指令 75 | 76 | > 首先您需要确定NDKcore.a确实存在,它位于./lib/NDKcore.a,否则请使用make image编译源代码,再进入./command目录使用make install,而使用make install您必须确保80m.img存在,您也可以修改makeflie 77 | 78 | 直接进入./command目录使用make install编译应用 79 | 80 | END. 81 | 82 | 83 | 84 | **最后,感谢您的耐心阅读和为NanoOS编写软件** 85 | 86 | 87 | 88 | 参考书籍: 89 | 90 | ^《OrangeS:一个操作系统的实现》(于渊)电子工业出版社 2009-6-1 ISBN 9787121084423, 7121084422 91 | 92 | ^《操作系统设计与实现(第3版)》(Andrew S. Tanenbaum)清华大学出版社出版 2008-5-4 ISBN:9787302172765 93 | 94 | ^《一个64位操作系统的设计与实现》(田宇)人民邮电出版社 2018-5 ISBN: 9787115475251 95 | 96 | ^《Intel® 64 and IA-32 Architectures Software Developer Manuals》 (Intel Inc.)2016-10-12 -------------------------------------------------------------------------------- /a.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/a.img -------------------------------------------------------------------------------- /bochsrc: -------------------------------------------------------------------------------- 1 | ############################################################### 2 | # Configuration file for Bochs 3 | ############################################################### 4 | 5 | # how much memory the emulated machine will have 6 | megs: 32 7 | 8 | # filename of ROM images 9 | romimage: file=/usr/share/bochs/BIOS-bochs-latest 10 | vgaromimage: file=/usr/share/vgabios/vgabios.bin 11 | 12 | # what disk images will be used 13 | floppya: 1_44=a.img, status=inserted 14 | 15 | # hard disk 16 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 17 | # !! Remember to change these if the hd img is changed: 18 | # 1. include/sys/config.h::MINOR_BOOT 19 | # 2. boot/include/load.inc::ROOT_BASE 20 | # 3. Makefile::HD 21 | # 4. commands/Makefile::HD 22 | ata0-master: type=disk, path="80m.img", mode=flat, cylinders=162, heads=16, spt=63 23 | 24 | # choose the boot disk. 25 | boot: a 26 | 27 | # where do we send log messages? 28 | # log: bochsout.txt 29 | 30 | # disable the mouse 31 | mouse: enabled=0 32 | 33 | # enable key mapping, using US layout as default. 34 | keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map 35 | -------------------------------------------------------------------------------- /boot/boot.asm: -------------------------------------------------------------------------------- 1 | ;Hanbings 3219065882@qq.com 2 | 3 | %ifdef _BOOT_DEBUG_ 4 | org 0100h ; 调试状态, 做成 .COM 文件, 可调试 5 | %else 6 | org 07c00h ; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行 7 | %endif 8 | 9 | ;================================================================================================ 10 | %ifdef _BOOT_DEBUG_ 11 | BaseOfStack equ 0100h ; 调试状态下堆栈基地址(栈底, 从这个位置向低地址生长) 12 | %else 13 | BaseOfStack equ 07c00h ; Boot状态下堆栈基地址(栈底, 从这个位置向低地址生长) 14 | %endif 15 | 16 | %include "load.inc" 17 | ;================================================================================================ 18 | 19 | jmp short LABEL_START ; Start to boot. 20 | nop ; 这个 nop 不可少 21 | 22 | ; 下面是 FAT12 磁盘的头, 之所以包含它是因为下面用到了磁盘的一些信息 23 | %include "fat12hdr.inc" 24 | 25 | LABEL_START: 26 | mov ax, cs 27 | mov ds, ax 28 | mov es, ax 29 | mov ss, ax 30 | mov sp, BaseOfStack 31 | 32 | ; 清屏 33 | mov ax, 0600h ; AH = 6, AL = 0h 34 | mov bx, 0700h ; 黑底白字(BL = 07h) 35 | mov cx, 0 ; 左上角: (0, 0) 36 | mov dx, 0184fh ; 右下角: (80, 50) 37 | int 10h ; int 10h 38 | 39 | mov dh, 0 ; "Booting " 40 | call DispStr ; 显示字符串 41 | 42 | xor ah, ah ; ┓ 43 | xor dl, dl ; ┣ 软驱复位 44 | int 13h ; ┛ 45 | 46 | ; 下面在 A 盘的根目录寻找 LOADER.BIN 47 | mov word [wSectorNo], SectorNoOfRootDirectory 48 | LABEL_SEARCH_IN_ROOT_DIR_BEGIN: 49 | cmp word [wRootDirSizeForLoop], 0 ; ┓ 50 | jz LABEL_NO_LOADERBIN ; ┣ 判断根目录区是不是已经读完 51 | dec word [wRootDirSizeForLoop] ; ┛ 如果读完表示没有找到 LOADER.BIN 52 | mov ax, LOADER_SEG 53 | mov es, ax ; es <- LOADER_SEG 54 | mov bx, LOADER_OFF ; bx <- LOADER_OFF 于是, es:bx = LOADER_SEG:LOADER_OFF 55 | mov ax, [wSectorNo] ; ax <- Root Directory 中的某 Sector 号 56 | mov cl, 1 57 | call ReadSector 58 | 59 | mov si, LoaderFileName ; ds:si -> "LOADER BIN" 60 | mov di, LOADER_OFF ; es:di -> LOADER_SEG:0100 = LOADER_SEG*10h+100 61 | cld 62 | mov dx, 10h 63 | LABEL_SEARCH_FOR_LOADERBIN: 64 | cmp dx, 0 ; ┓循环次数控制, 65 | jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR ; ┣如果已经读完了一个 Sector, 66 | dec dx ; ┛就跳到下一个 Sector 67 | mov cx, 11 68 | LABEL_CMP_FILENAME: 69 | cmp cx, 0 70 | jz LABEL_FILENAME_FOUND ; 如果比较了 11 个字符都相等, 表示找到 71 | dec cx 72 | lodsb ; ds:si -> al 73 | cmp al, byte [es:di] 74 | jz LABEL_GO_ON 75 | jmp LABEL_DIFFERENT ; 只要发现不一样的字符就表明本 DirectoryEntry 不是 76 | ; 我们要找的 LOADER.BIN 77 | LABEL_GO_ON: 78 | inc di 79 | jmp LABEL_CMP_FILENAME ; 继续循环 80 | 81 | LABEL_DIFFERENT: 82 | and di, 0FFE0h ; else ┓ di &= E0 为了让它指向本条目开头 83 | add di, 20h ; ┃ 84 | mov si, LoaderFileName ; ┣ di += 20h 下一个目录条目 85 | jmp LABEL_SEARCH_FOR_LOADERBIN; ┛ 86 | 87 | LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR: 88 | add word [wSectorNo], 1 89 | jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN 90 | 91 | LABEL_NO_LOADERBIN: 92 | mov dh, 2 ; "No LOADER." 93 | call DispStr ; 显示字符串 94 | %ifdef _BOOT_DEBUG_ 95 | mov ax, 4c00h ; ┓ 96 | int 21h ; ┛没有找到 LOADER.BIN, 回到 DOS 97 | %else 98 | jmp $ ; 没有找到 LOADER.BIN, 死循环在这里 99 | %endif 100 | 101 | LABEL_FILENAME_FOUND: ; 找到 LOADER.BIN 后便来到这里继续 102 | mov ax, RootDirSectors 103 | and di, 0FFE0h ; di -> 当前条目的开始 104 | add di, 01Ah ; di -> 首 Sector 105 | mov cx, word [es:di] 106 | push cx ; 保存此 Sector 在 FAT 中的序号 107 | add cx, ax 108 | add cx, DeltaSectorNo ; 这句完成时 cl 里面变成 LOADER.BIN 的起始扇区号 (从 0 开始数的序号) 109 | mov ax, LOADER_SEG 110 | mov es, ax ; es <- LOADER_SEG 111 | mov bx, LOADER_OFF ; bx <- LOADER_OFF 于是, es:bx = LOADER_SEG:LOADER_OFF = LOADER_SEG * 10h + LOADER_OFF 112 | mov ax, cx ; ax <- Sector 号 113 | 114 | LABEL_GOON_LOADING_FILE: 115 | push ax ; ┓ 116 | push bx ; ┃ 117 | mov ah, 0Eh ; ┃ 每读一个扇区就在 "Booting " 后面打一个点, 形成这样的效果: 118 | mov al, '.' ; ┃ 119 | mov bl, 0Fh ; ┃ Booting ...... 120 | int 10h ; ┃ 121 | pop bx ; ┃ 122 | pop ax ; ┛ 123 | 124 | mov cl, 1 125 | call ReadSector 126 | pop ax ; 取出此 Sector 在 FAT 中的序号 127 | call GetFATEntry 128 | cmp ax, 0FFFh 129 | jz LABEL_FILE_LOADED 130 | push ax ; 保存 Sector 在 FAT 中的序号 131 | mov dx, RootDirSectors 132 | add ax, dx 133 | add ax, DeltaSectorNo 134 | add bx, [BPB_BytsPerSec] 135 | jmp LABEL_GOON_LOADING_FILE 136 | LABEL_FILE_LOADED: 137 | 138 | mov dh, 1 ; "Ready." 139 | call DispStr ; 显示字符串 140 | 141 | ; ***************************************************************************************************** 142 | jmp LOADER_SEG:LOADER_OFF ; 这一句正式跳转到已加载到内存中的 LOADER.BIN 的开始处 143 | ; 开始执行 LOADER.BIN 的代码 144 | ; Boot Sector 的使命到此结束 145 | ; ***************************************************************************************************** 146 | 147 | 148 | 149 | ;============================================================================ 150 | ;变量 151 | ;---------------------------------------------------------------------------- 152 | wRootDirSizeForLoop dw RootDirSectors ; Root Directory 占用的扇区数, 在循环中会递减至零. 153 | wSectorNo dw 0 ; 要读取的扇区号 154 | bOdd db 0 ; 奇数还是偶数 155 | 156 | ;============================================================================ 157 | ;字符串 158 | ;---------------------------------------------------------------------------- 159 | LoaderFileName db "LOADER BIN", 0 ; LOADER.BIN 之文件名 160 | ; 为简化代码, 下面每个字符串的长度均为 MessageLength 161 | MessageLength equ 19 162 | BootMessage: db "[INFO]Boot Loader " 163 | Message1 db "[INFO]Loader Loaded" 164 | Message2 db " " 165 | ;============================================================================ 166 | 167 | 168 | ;---------------------------------------------------------------------------- 169 | ; 函数名: DispStr 170 | ;---------------------------------------------------------------------------- 171 | ; 作用: 172 | ; 显示一个字符串, 函数开始时 dh 中应该是字符串序号(0-based) 173 | DispStr: 174 | mov ax, MessageLength 175 | mul dh 176 | add ax, BootMessage 177 | mov bp, ax ; ┓ 178 | mov ax, ds ; ┣ ES:BP = 串地址 179 | mov es, ax ; ┛ 180 | mov cx, MessageLength ; CX = 串长度 181 | mov ax, 01301h ; AH = 13, AL = 01h 182 | mov bx, 000ah ; 页号为0(BH = 0) 黑底白字(BL = 07h) 183 | mov dl, 0 184 | int 10h ; int 10h 185 | ret 186 | 187 | 188 | ;---------------------------------------------------------------------------- 189 | ; 函数名: ReadSector 190 | ;---------------------------------------------------------------------------- 191 | ; 作用: 192 | ; 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中 193 | ReadSector: 194 | ; ----------------------------------------------------------------------- 195 | ; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号) 196 | ; ----------------------------------------------------------------------- 197 | ; 设扇区号为 x 198 | ; ┌ 柱面号 = y >> 1 199 | ; x ┌ 商 y ┤ 200 | ; -------------- => ┤ └ 磁头号 = y & 1 201 | ; 每磁道扇区数 │ 202 | ; └ 余 z => 起始扇区号 = z + 1 203 | push bp 204 | mov bp, sp 205 | sub esp, 2 ; 辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2] 206 | 207 | mov byte [bp-2], cl 208 | push bx ; 保存 bx 209 | mov bl, [BPB_SecPerTrk] ; bl: 除数 210 | div bl ; y 在 al 中, z 在 ah 中 211 | inc ah ; z ++ 212 | mov cl, ah ; cl <- 起始扇区号 213 | mov dh, al ; dh <- y 214 | shr al, 1 ; y >> 1 (其实是 y/BPB_NumHeads, 这里BPB_NumHeads=2) 215 | mov ch, al ; ch <- 柱面号 216 | and dh, 1 ; dh & 1 = 磁头号 217 | pop bx ; 恢复 bx 218 | ; 至此, "柱面号, 起始扇区, 磁头号" 全部得到 ^^^^^^^^^^^^^^^^^^^^^^^^ 219 | mov dl, [BS_DrvNum] ; 驱动器号 (0 表示 A 盘) 220 | .GoOnReading: 221 | mov ah, 2 ; 读 222 | mov al, byte [bp-2] ; 读 al 个扇区 223 | int 13h 224 | jc .GoOnReading ; 如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止 225 | 226 | add esp, 2 227 | pop bp 228 | 229 | ret 230 | 231 | ;---------------------------------------------------------------------------- 232 | ; 函数名: GetFATEntry 233 | ;---------------------------------------------------------------------------- 234 | ; 作用: 235 | ; 找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中 236 | ; 需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bx 237 | GetFATEntry: 238 | push es 239 | push bx 240 | push ax 241 | mov ax, LOADER_SEG ; ┓ 242 | sub ax, 0100h ; ┣ 在 LOADER_SEG 后面留出 4K 空间用于存放 FAT 243 | mov es, ax ; ┛ 244 | pop ax 245 | mov byte [bOdd], 0 246 | mov bx, 3 247 | mul bx ; dx:ax = ax * 3 248 | mov bx, 2 249 | div bx ; dx:ax / 2 ==> ax <- 商, dx <- 余数 250 | cmp dx, 0 251 | jz LABEL_EVEN 252 | mov byte [bOdd], 1 253 | LABEL_EVEN:;偶数 254 | xor dx, dx ; 现在 ax 中是 FATEntry 在 FAT 中的偏移量. 下面来计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区) 255 | mov bx, [BPB_BytsPerSec] 256 | div bx ; dx:ax / BPB_BytsPerSec ==> ax <- 商 (FATEntry 所在的扇区相对于 FAT 来说的扇区号) 257 | ; dx <- 余数 (FATEntry 在扇区内的偏移)。 258 | push dx 259 | mov bx, 0 ; bx <- 0 于是, es:bx = (LOADER_SEG - 100):00 = (LOADER_SEG - 100) * 10h 260 | add ax, SectorNoOfFAT1 ; 此句执行之后的 ax 就是 FATEntry 所在的扇区号 261 | mov cl, 2 262 | call ReadSector ; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界发生错误, 因为一个 FATEntry 可能跨越两个扇区 263 | pop dx 264 | add bx, dx 265 | mov ax, [es:bx] 266 | cmp byte [bOdd], 1 267 | jnz LABEL_EVEN_2 268 | shr ax, 4 269 | LABEL_EVEN_2: 270 | and ax, 0FFFh 271 | 272 | LABEL_GET_FAT_ENRY_OK: 273 | 274 | pop bx 275 | pop es 276 | ret 277 | ;---------------------------------------------------------------------------- 278 | 279 | times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节 280 | dw 0xaa55 ; 结束标志 281 | -------------------------------------------------------------------------------- /boot/boot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/boot/boot.bin -------------------------------------------------------------------------------- /boot/include/fat12hdr.inc: -------------------------------------------------------------------------------- 1 | 2 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | ; fat12hdr.inc 4 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | ; Forrest Yu, 2005 6 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | 9 | ; FAT12 磁盘的头 10 | ; ---------------------------------------------------------------------- 11 | BS_OEMName DB 'NANOZERO' ; OEM String, 必须 8 个字节 12 | 13 | BPB_BytsPerSec DW 512 ; 每扇区字节数 14 | BPB_SecPerClus DB 1 ; 每簇多少扇区 15 | BPB_RsvdSecCnt DW 1 ; Boot 记录占用多少扇区 16 | BPB_NumFATs DB 2 ; 共有多少 FAT 表 17 | BPB_RootEntCnt DW 224 ; 根目录文件数最大值 18 | BPB_TotSec16 DW 2880 ; 逻辑扇区总数 19 | BPB_Media DB 0xF0 ; 媒体描述符 20 | BPB_FATSz16 DW 9 ; 每FAT扇区数 21 | BPB_SecPerTrk DW 18 ; 每磁道扇区数 22 | BPB_NumHeads DW 2 ; 磁头数(面数) 23 | BPB_HiddSec DD 0 ; 隐藏扇区数 24 | BPB_TotSec32 DD 0 ; 如果 wTotalSectorCount 是 0 由这个值记录扇区数 25 | 26 | BS_DrvNum DB 0 ; 中断 13 的驱动器号 27 | BS_Reserved1 DB 0 ; 未使用 28 | BS_BootSig DB 29h ; 扩展引导标记 (29h) 29 | BS_VolID DD 0 ; 卷序列号 30 | BS_VolLab DB 'NanoBooter '; 卷标, 必须 11 个字节 31 | BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节 32 | ;------------------------------------------------------------------------ 33 | 34 | 35 | ; ------------------------------------------------------------------------- 36 | ; 基于 FAT12 头的一些常量定义,如果头信息改变,下面的常量可能也要做相应改变 37 | ; ------------------------------------------------------------------------- 38 | FATSz equ 9 ; BPB_FATSz16 39 | RootDirSectors equ 14 ; 根目录占用空间: RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec; 但如果按照此公式代码过长 40 | SectorNoOfRootDirectory equ 19 ; Root Directory 的第一个扇区号 = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) 41 | SectorNoOfFAT1 equ 1 ; FAT1 的第一个扇区号 = BPB_RsvdSecCnt 42 | DeltaSectorNo equ 17 ; DeltaSectorNo = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) - 2 43 | ; 文件的开始Sector号 = DirEntry中的开始Sector号 + 根目录占用Sector数目 + DeltaSectorNo 44 | -------------------------------------------------------------------------------- /boot/include/load.inc: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;; boot/include/load.inc 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4 | 5 | ;; kernel entry point, corresponding with Makefile 6 | KRNL_ENT_PT_PHY_ADDR equ 0x1000 7 | 8 | ;; paging 9 | PAGE_DIR_BASE equ 0x100000 10 | PAGE_TBL_BASE equ 0x101000 11 | 12 | ;; where loader is loaded 13 | LOADER_SEG equ 0x9000 14 | LOADER_OFF equ 0x100 15 | LOADER_PHY_ADDR equ LOADER_SEG * 0x10 16 | 17 | ;; where kernel file is loaded 18 | KERNEL_FILE_SEG equ 0x7000 19 | KERNEL_FILE_OFF equ 0 20 | KERNEL_FILE_PHY_ADDR equ KERNEL_FILE_SEG * 0x10 21 | 22 | ; bytes reserved for kernel.bin 23 | KERNEL_VALID_SPACE equ LOADER_PHY_ADDR - KERNEL_FILE_PHY_ADDR 24 | 25 | ;; super block will be stored at: [0x700,0x900) 26 | SUPER_BLK_SEG equ 0x70 27 | 28 | ;; ATTENTION: 29 | ;; Macros below should corresponding with C source. 30 | BOOT_PARAM_ADDR equ 0x900 31 | BOOT_PARAM_MAGIC equ 0xB007 32 | 33 | ;; we don't calculate the base sector nr of the root device while loading 34 | ;; but define it as a macro for two reasons: 35 | ;; 1. it is a constant for any certain system 36 | ;; 2. it simplifies boot sector and loader 37 | ROOT_BASE equ 0x4EFF 38 | 39 | ;; corresponding with include/sys/fs.h 40 | SB_MAGIC_V1 equ 0x111 41 | SB_MAGIC equ 4 * 0 42 | SB_NR_INODES equ 4 * 1 43 | SB_NR_SECTS equ 4 * 2 44 | SB_NR_IMAP_SECTS equ 4 * 3 45 | SB_NR_SMAP_SECTS equ 4 * 4 46 | SB_N_1ST_SECT equ 4 * 5 47 | SB_NR_INODE_SECTS equ 4 * 6 48 | SB_ROOT_INODE equ 4 * 7 49 | SB_INODE_SIZE equ 4 * 8 50 | SB_INODE_ISIZE_OFF equ 4 * 9 51 | SB_INODE_START_OFF equ 4 * 10 52 | SB_DIR_ENT_SIZE equ 4 * 11 53 | SB_DIR_ENT_INODE_OFF equ 4 * 12 54 | SB_DIR_ENT_FNAME_OFF equ 4 * 13 55 | 56 | -------------------------------------------------------------------------------- /boot/loader.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/boot/loader.bin -------------------------------------------------------------------------------- /command/Makefile: -------------------------------------------------------------------------------- 1 | # commands/Makefile 2 | 3 | #ENTRYPOINT = 0x1000 4 | HD = ../80m.vmdk 5 | 6 | ASM = nasm 7 | DASM = objdump 8 | CC = gcc 9 | LD = ld 10 | ASMFLAGS = -I ../include/ -f elf 11 | CFLAGS = -I ../include/ -m32 -c -fno-builtin -Wall -fno-stack-protector 12 | LDFLAGS = -m elf_i386 -s -Ttext 0x1000 13 | DASMFLAGS = -D 14 | LIB = ../lib/NDKcore.a 15 | BIN = echo pwd 16 | 17 | # All Phony Targets 18 | .PHONY : everything final clean realclean disasm all install 19 | 20 | # Default starting position 21 | everything : $(BIN) 22 | 23 | install : all clean 24 | cp ../kernel.bin ./ -v 25 | tar vcf inst.tar kernel.bin $(BIN) 26 | dd if=inst.tar of=$(HD) seek=`echo "obase=10;ibase=16;(\`egrep -e '^ROOT_BASE' ../boot/include/load.inc | sed -e 's/.*0x//g'\`+\`egrep -e '#define[[:space:]]*INSTALL_START_SECT' ../include/sys/config.h | sed -e 's/.*0x//g'\`)*200" | bc` bs=1 count=`ls -l inst.tar | awk -F " " '{print $$5}'` conv=notrunc 27 | 28 | all : realclean everything 29 | 30 | final : all clean 31 | 32 | clean : 33 | rm -f *.o 34 | 35 | realclean : 36 | rm -f $(BIN) *.o 37 | 38 | kernel.bin : 39 | cp ../kernel.bin ./ 40 | 41 | start.o : start.asm 42 | $(ASM) $(ASMFLAGS) -o $@ $< 43 | 44 | echo.o: echo.c ../include/type.h ../include/stdio.h 45 | $(CC) $(CFLAGS) -o $@ $< 46 | 47 | echo : echo.o start.o $(LIB) 48 | $(LD) $(LDFLAGS) -o $@ $? 49 | 50 | pwd.o: pwd.c ../include/type.h ../include/stdio.h 51 | $(CC) $(CFLAGS) -o $@ $< 52 | 53 | pwd : pwd.o start.o $(LIB) 54 | $(LD) $(LDFLAGS) -o $@ $? 55 | -------------------------------------------------------------------------------- /command/echo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/command/echo -------------------------------------------------------------------------------- /command/echo.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "stdio.h" 3 | 4 | int main(int argc, char * argv[]) 5 | { 6 | int i; 7 | for (i = 1; i < argc; i++) 8 | printf("%s%s", i == 1 ? "" : " ", argv[i]); 9 | printf("\n"); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /command/inst.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/command/inst.tar -------------------------------------------------------------------------------- /command/kernel.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/command/kernel.bin -------------------------------------------------------------------------------- /command/pwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/command/pwd -------------------------------------------------------------------------------- /command/pwd.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "type.h" 3 | #include "stdio.h" 4 | //#include "color.h" 5 | 6 | int main(int argc, char * argv[]) 7 | { 8 | printf("This is My First APP!!\n"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /command/start.asm: -------------------------------------------------------------------------------- 1 | ;; start.asm 2 | 3 | extern main 4 | extern exit 5 | 6 | bits 32 7 | 8 | [section .text] 9 | 10 | global _start 11 | 12 | _start: 13 | push eax 14 | push ecx 15 | call main 16 | ;; need not clean up the stack here 17 | 18 | push eax 19 | call exit 20 | 21 | hlt ; should never arrive here 22 | 23 | -------------------------------------------------------------------------------- /include/color.h: -------------------------------------------------------------------------------- 1 | 2 | /*颜色*/ 3 | 4 | int blackBlackColor = 0x00; 5 | /*黑底黑字*/ 6 | int blackBlueColor = 0x01; 7 | /*黑底蓝字*/ 8 | int blackGreeenColor = 0x02; 9 | /*黑底绿字*/ 10 | int blackCyanColor = 0x03; 11 | /*黑底灰字*/ 12 | int blackRedColor = 0x04; 13 | /*黑底红字*/ 14 | int blackMagentaColor = 0x05; 15 | /*黑底紫字*/ 16 | int blackYellowColor = 0x06; 17 | /*黑底黄字*/ 18 | int blackWhiteColor = 0x07; 19 | /*黑底白字*/ 20 | int blackGrayColor = 0x08; 21 | /*黑底灰字*/ 22 | int blackBrightBlueColor = 0x09; 23 | /*黑底亮蓝*/ 24 | int blackBrightGreenColor = 0x0a; 25 | /*黑底高绿*/ 26 | int blackBrightCyanColor = 0x0b; 27 | /*黑底高灰*/ 28 | int blackBrightBrightRedColor = 0x0c; 29 | /*黑底高红*/ 30 | 31 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #ifndef _ORANGES_STDIO_H_ 4 | #define _ORANGES_STDIO_H_ 5 | 6 | #include "type.h" 7 | 8 | /* the assert macro */ 9 | #define ASSERT 10 | #ifdef ASSERT 11 | void assertion_failure(char *exp, char *file, char *base_file, int line); 12 | #define assert(exp) if (exp) ; \ 13 | else assertion_failure(#exp, __FILE__, __BASE_FILE__, __LINE__) 14 | #else 15 | #define assert(exp) 16 | #endif 17 | 18 | /* EXTERN */ 19 | #define EXTERN extern /* EXTERN is defined as extern except in global.c */ 20 | 21 | /* string */ 22 | #define STR_DEFAULT_LEN 1024 23 | 24 | #define O_CREAT 1 25 | #define O_RDWR 2 26 | 27 | #define SEEK_SET 1 28 | #define SEEK_CUR 2 29 | #define SEEK_END 3 30 | 31 | #define MAX_PATH 128 32 | 33 | /** 34 | * @struct stat 35 | * @brief File status, returned by syscall stat(); 36 | */ 37 | struct stat { 38 | int st_dev; /* major/minor device number */ 39 | int st_ino; /* i-node number */ 40 | int st_mode; /* file mode, protection bits, etc. */ 41 | int st_rdev; /* device ID (if special file) */ 42 | int st_size; /* file size */ 43 | }; 44 | 45 | /** 46 | * @struct time 47 | * @brief RTC time from CMOS. 48 | */ 49 | struct time { 50 | u32 year; 51 | u32 month; 52 | u32 day; 53 | u32 hour; 54 | u32 minute; 55 | u32 second; 56 | }; 57 | 58 | #define BCD_TO_DEC(x) ( (x >> 4) * 10 + (x & 0x0f) ) 59 | 60 | /*========================* 61 | * printf, printl, printx * 62 | *========================* 63 | * 64 | * printf: 65 | * 66 | * [send msg] WRITE DEV_WRITE 67 | * USER_PROC ------------→ FS -------------→ TTY 68 | * ↖______________↙↖_______________/ 69 | * [recv msg] SYSCALL_RET SYSCALL_RET 70 | * 71 | *---------------------------------------------------------------------- 72 | * 73 | * printl: variant-parameter-version printx 74 | * 75 | * calls vsprintf, then printx (trap into kernel directly) 76 | * 77 | *---------------------------------------------------------------------- 78 | * 79 | * printx: low level print without using IPC 80 | * 81 | * trap directly 82 | * USER_PROC -- -- -- -- -- --> KERNEL 83 | * 84 | * 85 | *---------------------------------------------------------------------- 86 | */ 87 | 88 | /* printf.c */ 89 | PUBLIC int printf(const char *fmt, ...); 90 | PUBLIC int printl(const char *fmt, ...); 91 | 92 | /* vsprintf.c */ 93 | PUBLIC int vsprintf(char *buf, const char *fmt, va_list args); 94 | PUBLIC int sprintf(char *buf, const char *fmt, ...); 95 | 96 | /*--------*/ 97 | /* 库函数 */ 98 | /*--------*/ 99 | 100 | #ifdef ENABLE_DISK_LOG 101 | #define SYSLOG syslog 102 | #endif 103 | 104 | /* lib/open.c */ 105 | PUBLIC int open (const char *pathname, int flags); 106 | 107 | /* lib/close.c */ 108 | PUBLIC int close (int fd); 109 | 110 | /* lib/read.c */ 111 | PUBLIC int read (int fd, void *buf, int count); 112 | 113 | /* lib/write.c */ 114 | PUBLIC int write (int fd, const void *buf, int count); 115 | 116 | /* lib/unlink.c */ 117 | PUBLIC int unlink (const char *pathname); 118 | 119 | /* lib/getpid.c */ 120 | PUBLIC int getpid (); 121 | 122 | /* lib/fork.c */ 123 | PUBLIC int fork (); 124 | 125 | /* lib/exit.c */ 126 | PUBLIC void exit (int status); 127 | 128 | /* lib/wait.c */ 129 | PUBLIC int wait (int * status); 130 | 131 | /* lib/exec.c */ 132 | PUBLIC int exec (const char * path); 133 | PUBLIC int execl (const char * path, const char *arg, ...); 134 | PUBLIC int execv (const char * path, char * argv[]); 135 | 136 | /* lib/stat.c */ 137 | PUBLIC int stat (const char *path, struct stat *buf); 138 | 139 | /* lib/syslog.c */ 140 | PUBLIC int syslog (const char *fmt, ...); 141 | 142 | 143 | /* lib/color.c */ 144 | PUBLIC void printfInfo(); 145 | PUBLIC void printfWarn(); 146 | PUBLIC void printfErro(); 147 | PUBLIC void printfInfoNotReturn(); 148 | PUBLIC void printfWarnNotReturn(); 149 | PUBLIC void printfErroNotReturn(); 150 | 151 | 152 | #endif /* _ORANGES_STDIO_H_ */ 153 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | PUBLIC void* memcpy(void* p_dst, void* p_src, int size); 4 | PUBLIC void memset(void* p_dst, char ch, int size); 5 | PUBLIC int strlen(const char* p_str); 6 | PUBLIC int memcmp(const void * s1, const void *s2, int n); 7 | PUBLIC int strcmp(const char * s1, const char *s2); 8 | PUBLIC char* strcat(char * s1, const char *s2); 9 | 10 | #define phys_copy memcpy 11 | #define phys_set memset 12 | 13 | -------------------------------------------------------------------------------- /include/sys/config.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************//** 2 | ***************************************************************************** 3 | * @file config.h 4 | * @brief 5 | * @author Forrest Y. Yu 6 | * @date 2008 7 | ***************************************************************************** 8 | *****************************************************************************/ 9 | 10 | /** 11 | * Some sector are reserved for us (the gods of the os) to copy a tar file 12 | * there, which will be extracted and used by the OS. 13 | * 14 | * @attention INSTALL_NR_SECTS should be a multiple of NR_DEFAULT_FILE_SECTS: 15 | * INSTALL_NR_SECTS = n * NR_DEFAULT_FILE_SECTS (n=1,2,3,...) 16 | */ 17 | #define INSTALL_START_SECT 0x8000 18 | #define INSTALL_NR_SECTS 0x800 19 | 20 | /** 21 | * boot parameters are stored by the loader, they should be 22 | * there when kernel is running and should not be overwritten 23 | * since kernel might use them at any time. 24 | */ 25 | #define BOOT_PARAM_ADDR 0x900 /* physical address */ 26 | #define BOOT_PARAM_MAGIC 0xB007 /* magic number */ 27 | #define BI_MAG 0 28 | #define BI_MEM_SIZE 1 29 | #define BI_KERNEL_FILE 2 30 | 31 | /** 32 | * corresponding with boot/include/load.inc::ROOT_BASE, which should 33 | * be changed if this macro is changed. 34 | */ 35 | #define MINOR_BOOT MINOR_hd2a 36 | 37 | /* 38 | * disk log 39 | */ 40 | #define ENABLE_DISK_LOG 41 | #define SET_LOG_SECT_SMAP_AT_STARTUP 42 | #define MEMSET_LOG_SECTS 43 | #define NR_SECTS_FOR_LOG NR_DEFAULT_FILE_SECTS 44 | -------------------------------------------------------------------------------- /include/sys/console.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | console.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | #ifndef _ORANGES_CONSOLE_H_ 9 | #define _ORANGES_CONSOLE_H_ 10 | 11 | /* CONSOLE */ 12 | typedef struct s_console 13 | { 14 | unsigned int crtc_start; /* set CRTC start addr reg */ 15 | unsigned int orig; /* start addr of the console */ 16 | unsigned int con_size; /* how many words does the console have */ 17 | unsigned int cursor; 18 | int is_full; 19 | }CONSOLE; 20 | 21 | 22 | #define SCR_UP 1 /* scroll upward */ 23 | #define SCR_DN -1 /* scroll downward */ 24 | 25 | #define SCR_SIZE (80 * 25) 26 | #define SCR_WIDTH 80 27 | 28 | #define DEFAULT_CHAR_COLOR (MAKE_COLOR(BLACK, WHITE)) 29 | #define GRAY_CHAR (MAKE_COLOR(BLACK, BLACK) | BRIGHT) 30 | #define RED_CHAR (MAKE_COLOR(BLUE, RED) | BRIGHT) 31 | 32 | #endif /* _ORANGES_CONSOLE_H_ */ 33 | -------------------------------------------------------------------------------- /include/sys/const.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | const.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | #ifndef _ORANGES_CONST_H_ 9 | #define _ORANGES_CONST_H_ 10 | 11 | /* max() & min() */ 12 | #define max(a,b) ((a) > (b) ? (a) : (b)) 13 | #define min(a,b) ((a) < (b) ? (a) : (b)) 14 | 15 | /* Color */ 16 | /* 17 | * e.g. MAKE_COLOR(BLUE, RED) 18 | * MAKE_COLOR(BLACK, RED) | BRIGHT 19 | * MAKE_COLOR(BLACK, RED) | BRIGHT | FLASH 20 | */ 21 | #define BLACK 0x0 /* 0000 */ 22 | #define WHITE 0x7 /* 0111 */ 23 | #define RED 0x4 /* 0100 */ 24 | #define GREEN 0x2 /* 0010 */ 25 | #define BLUE 0x1 /* 0001 */ 26 | #define FLASH 0x80 /* 1000 0000 */ 27 | #define BRIGHT 0x08 /* 0000 1000 */ 28 | #define MAKE_COLOR(x,y) ((x<<4) | y) /* MAKE_COLOR(Background,Foreground) */ 29 | 30 | /* GDT 和 IDT 中描述符的个数 */ 31 | #define GDT_SIZE 128 32 | #define IDT_SIZE 256 33 | 34 | /* 权限 */ 35 | #define PRIVILEGE_KRNL 0 36 | #define PRIVILEGE_TASK 1 37 | #define PRIVILEGE_USER 3 38 | /* RPL */ 39 | #define RPL_KRNL SA_RPL0 40 | #define RPL_TASK SA_RPL1 41 | #define RPL_USER SA_RPL3 42 | 43 | /* Process */ 44 | #define SENDING 0x02 /* set when proc trying to send */ 45 | #define RECEIVING 0x04 /* set when proc trying to recv */ 46 | #define WAITING 0x08 /* set when proc waiting for the child to terminate */ 47 | #define HANGING 0x10 /* set when proc exits without being waited by parent */ 48 | #define FREE_SLOT 0x20 /* set when proc table entry is not used 49 | * (ok to allocated to a new process) 50 | */ 51 | 52 | /* TTY */ 53 | #define NR_CONSOLES 3 /* consoles */ 54 | 55 | /* 8259A interrupt controller ports. */ 56 | #define INT_M_CTL 0x20 /* I/O port for interrupt controller */ 57 | #define INT_M_CTLMASK 0x21 /* setting bits in this port disables ints */ 58 | #define INT_S_CTL 0xA0 /* I/O port for second interrupt controller */ 59 | #define INT_S_CTLMASK 0xA1 /* setting bits in this port disables ints */ 60 | 61 | /* 8253/8254 PIT (Programmable Interval Timer) */ 62 | #define TIMER0 0x40 /* I/O port for timer channel 0 */ 63 | #define TIMER_MODE 0x43 /* I/O port for timer mode control */ 64 | #define RATE_GENERATOR 0x34 /* 00-11-010-0 : 65 | * Counter0 - LSB then MSB - rate generator - binary 66 | */ 67 | #define TIMER_FREQ 1193182L/* clock frequency for timer in PC and AT */ 68 | #define HZ 100 /* clock freq (software settable on IBM-PC) */ 69 | 70 | /* AT keyboard */ 71 | /* 8042 ports */ 72 | #define KB_DATA 0x60 /* I/O port for keyboard data 73 | Read : Read Output Buffer 74 | Write: Write Input Buffer(8042 Data&8048 Command) */ 75 | #define KB_CMD 0x64 /* I/O port for keyboard command 76 | Read : Read Status Register 77 | Write: Write Input Buffer(8042 Command) */ 78 | #define LED_CODE 0xED 79 | #define KB_ACK 0xFA 80 | 81 | /* VGA */ 82 | #define CRTC_ADDR_REG 0x3D4 /* CRT Controller Registers - Addr Register */ 83 | #define CRTC_DATA_REG 0x3D5 /* CRT Controller Registers - Data Register */ 84 | #define START_ADDR_H 0xC /* reg index of video mem start addr (MSB) */ 85 | #define START_ADDR_L 0xD /* reg index of video mem start addr (LSB) */ 86 | #define CURSOR_H 0xE /* reg index of cursor position (MSB) */ 87 | #define CURSOR_L 0xF /* reg index of cursor position (LSB) */ 88 | #define V_MEM_BASE 0xB8000 /* base of color video memory */ 89 | #define V_MEM_SIZE 0x8000 /* 32K: B8000H -> BFFFFH */ 90 | 91 | /* CMOS */ 92 | #define CLK_ELE 0x70 /* CMOS RAM address register port (write only) 93 | * Bit 7 = 1 NMI disable 94 | * 0 NMI enable 95 | * Bits 6-0 = RAM address 96 | */ 97 | 98 | #define CLK_IO 0x71 /* CMOS RAM data register port (read/write) */ 99 | 100 | #define YEAR 9 /* Clock register addresses in CMOS RAM */ 101 | #define MONTH 8 102 | #define DAY 7 103 | #define HOUR 4 104 | #define MINUTE 2 105 | #define SECOND 0 106 | #define CLK_STATUS 0x0B /* Status register B: RTC configuration */ 107 | #define CLK_HEALTH 0x0E /* Diagnostic status: (should be set by Power 108 | * On Self-Test [POST]) 109 | * Bit 7 = RTC lost power 110 | * 6 = Checksum (for addr 0x10-0x2d) bad 111 | * 5 = Config. Info. bad at POST 112 | * 4 = Mem. size error at POST 113 | * 3 = I/O board failed initialization 114 | * 2 = CMOS time invalid 115 | * 1-0 = reserved 116 | */ 117 | 118 | /* Hardware interrupts */ 119 | #define NR_IRQ 16 /* Number of IRQs */ 120 | #define CLOCK_IRQ 0 121 | #define KEYBOARD_IRQ 1 122 | #define CASCADE_IRQ 2 /* cascade enable for 2nd AT controller */ 123 | #define ETHER_IRQ 3 /* default ethernet interrupt vector */ 124 | #define SECONDARY_IRQ 3 /* RS232 interrupt vector for port 2 */ 125 | #define RS232_IRQ 4 /* RS232 interrupt vector for port 1 */ 126 | #define XT_WINI_IRQ 5 /* xt winchester */ 127 | #define FLOPPY_IRQ 6 /* floppy disk */ 128 | #define PRINTER_IRQ 7 129 | #define AT_WINI_IRQ 14 /* at winchester */ 130 | 131 | /* tasks */ 132 | /* 注意 TASK_XXX 的定义要与 global.c 中对应 */ 133 | #define INVALID_DRIVER -20 134 | #define INTERRUPT -10 135 | #define TASK_TTY 0 136 | #define TASK_SYS 1 137 | #define TASK_HD 2 138 | #define TASK_FS 3 139 | #define TASK_MM 4 140 | #define INIT 5 141 | #define ANY (NR_TASKS + NR_PROCS + 10) 142 | #define NO_TASK (NR_TASKS + NR_PROCS + 20) 143 | 144 | #define MAX_TICKS 0x7FFFABCD 145 | 146 | /* system call */ 147 | #define NR_SYS_CALL 3 148 | 149 | /* ipc */ 150 | #define SEND 1 151 | #define RECEIVE 2 152 | #define BOTH 3 /* BOTH = (SEND | RECEIVE) */ 153 | 154 | /* magic chars used by `printx' */ 155 | #define MAG_CH_PANIC '\002' 156 | #define MAG_CH_ASSERT '\003' 157 | 158 | /** 159 | * @enum msgtype 160 | * @brief MESSAGE types 161 | */ 162 | enum msgtype { 163 | /* 164 | * when hard interrupt occurs, a msg (with type==HARD_INT) will 165 | * be sent to some tasks 166 | */ 167 | HARD_INT = 1, 168 | 169 | /* SYS task */ 170 | GET_TICKS, GET_PID, GET_RTC_TIME, 171 | 172 | /* FS */ 173 | OPEN, CLOSE, READ, WRITE, LSEEK, STAT, UNLINK, 174 | 175 | /* FS & TTY */ 176 | SUSPEND_PROC, RESUME_PROC, 177 | 178 | /* MM */ 179 | EXEC, WAIT, 180 | 181 | /* FS & MM */ 182 | FORK, EXIT, 183 | 184 | /* TTY, SYS, FS, MM, etc */ 185 | SYSCALL_RET, 186 | 187 | /* message type for drivers */ 188 | DEV_OPEN = 1001, 189 | DEV_CLOSE, 190 | DEV_READ, 191 | DEV_WRITE, 192 | DEV_IOCTL 193 | }; 194 | 195 | /* macros for messages */ 196 | #define FD u.m3.m3i1 197 | #define PATHNAME u.m3.m3p1 198 | #define FLAGS u.m3.m3i1 199 | #define NAME_LEN u.m3.m3i2 200 | #define BUF_LEN u.m3.m3i3 201 | #define CNT u.m3.m3i2 202 | #define REQUEST u.m3.m3i2 203 | #define PROC_NR u.m3.m3i3 204 | #define DEVICE u.m3.m3i4 205 | #define POSITION u.m3.m3l1 206 | #define BUF u.m3.m3p2 207 | #define OFFSET u.m3.m3i2 208 | #define WHENCE u.m3.m3i3 209 | 210 | #define PID u.m3.m3i2 211 | #define RETVAL u.m3.m3i1 212 | #define STATUS u.m3.m3i1 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | #define DIOCTL_GET_GEO 1 223 | 224 | /* Hard Drive */ 225 | #define SECTOR_SIZE 512 226 | #define SECTOR_BITS (SECTOR_SIZE * 8) 227 | #define SECTOR_SIZE_SHIFT 9 228 | 229 | /* major device numbers (corresponding to kernel/global.c::dd_map[]) */ 230 | #define NO_DEV 0 231 | #define DEV_FLOPPY 1 232 | #define DEV_CDROM 2 233 | #define DEV_HD 3 234 | #define DEV_CHAR_TTY 4 235 | #define DEV_SCSI 5 236 | /* make device number from major and minor numbers */ 237 | #define MAJOR_SHIFT 8 238 | #define MAKE_DEV(a,b) ((a << MAJOR_SHIFT) | b) 239 | /* separate major and minor numbers from device number */ 240 | #define MAJOR(x) ((x >> MAJOR_SHIFT) & 0xFF) 241 | #define MINOR(x) (x & 0xFF) 242 | 243 | #define INVALID_INODE 0 244 | #define ROOT_INODE 1 245 | 246 | #define MAX_DRIVES 2 247 | #define NR_PART_PER_DRIVE 4 248 | #define NR_SUB_PER_PART 16 249 | #define NR_SUB_PER_DRIVE (NR_SUB_PER_PART * NR_PART_PER_DRIVE) 250 | #define NR_PRIM_PER_DRIVE (NR_PART_PER_DRIVE + 1) 251 | 252 | /** 253 | * @def MAX_PRIM 254 | * Defines the max minor number of the primary partitions. 255 | * If there are 2 disks, prim_dev ranges in hd[0-9], this macro will 256 | * equals 9. 257 | */ 258 | #define MAX_PRIM (MAX_DRIVES * NR_PRIM_PER_DRIVE - 1) 259 | 260 | #define MAX_SUBPARTITIONS (NR_SUB_PER_DRIVE * MAX_DRIVES) 261 | 262 | /* device numbers of hard disk */ 263 | #define MINOR_hd1a 0x10 264 | #define MINOR_hd2a (MINOR_hd1a+NR_SUB_PER_PART) 265 | 266 | #define ROOT_DEV MAKE_DEV(DEV_HD, MINOR_BOOT) 267 | 268 | #define P_PRIMARY 0 269 | #define P_EXTENDED 1 270 | 271 | #define ORANGES_PART 0x99 /* Orange'S partition */ 272 | #define NO_PART 0x00 /* unused entry */ 273 | #define EXT_PART 0x05 /* extended partition */ 274 | 275 | #define NR_FILES 64 276 | #define NR_FILE_DESC 64 /* FIXME */ 277 | #define NR_INODE 64 /* FIXME */ 278 | #define NR_SUPER_BLOCK 8 279 | 280 | 281 | /* INODE::i_mode (octal, lower 12 bits reserved) */ 282 | #define I_TYPE_MASK 0170000 283 | #define I_REGULAR 0100000 284 | #define I_BLOCK_SPECIAL 0060000 285 | #define I_DIRECTORY 0040000 286 | #define I_CHAR_SPECIAL 0020000 287 | #define I_NAMED_PIPE 0010000 288 | 289 | #define is_special(m) ((((m) & I_TYPE_MASK) == I_BLOCK_SPECIAL) || \ 290 | (((m) & I_TYPE_MASK) == I_CHAR_SPECIAL)) 291 | 292 | #define NR_DEFAULT_FILE_SECTS 2048 /* 2048 * 512 = 1MB */ 293 | 294 | 295 | 296 | #endif /* _ORANGES_CONST_H_ */ 297 | -------------------------------------------------------------------------------- /include/sys/fs.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************//** 2 | ***************************************************************************** 3 | * @file include/sys/fs.h 4 | * @brief Header file for File System. 5 | * @author Forrest Yu 6 | * @date 2008 7 | ***************************************************************************** 8 | *****************************************************************************/ 9 | 10 | #ifndef _ORANGES_FS_H_ 11 | #define _ORANGES_FS_H_ 12 | 13 | /** 14 | * @struct dev_drv_map fs.h "include/sys/fs.h" 15 | * @brief The Device_nr.\ - Driver_nr.\ MAP. 16 | */ 17 | struct dev_drv_map { 18 | int driver_nr; /**< The proc nr.\ of the device driver. */ 19 | }; 20 | 21 | /** 22 | * @def MAGIC_V1 23 | * @brief Magic number of FS v1.0 24 | */ 25 | #define MAGIC_V1 0x111 26 | 27 | /** 28 | * @struct super_block fs.h "include/fs.h" 29 | * @brief The 2nd sector of the FS 30 | * 31 | * Remember to change SUPER_BLOCK_SIZE if the members are changed. 32 | */ 33 | struct super_block { 34 | u32 magic; /**< Magic number */ 35 | u32 nr_inodes; /**< How many inodes */ 36 | u32 nr_sects; /**< How many sectors */ 37 | u32 nr_imap_sects; /**< How many inode-map sectors */ 38 | u32 nr_smap_sects; /**< How many sector-map sectors */ 39 | u32 n_1st_sect; /**< Number of the 1st data sector */ 40 | u32 nr_inode_sects; /**< How many inode sectors */ 41 | u32 root_inode; /**< Inode nr of root directory */ 42 | u32 inode_size; /**< INODE_SIZE */ 43 | u32 inode_isize_off; /**< Offset of `struct inode::i_size' */ 44 | u32 inode_start_off; /**< Offset of `struct inode::i_start_sect' */ 45 | u32 dir_ent_size; /**< DIR_ENTRY_SIZE */ 46 | u32 dir_ent_inode_off;/**< Offset of `struct dir_entry::inode_nr' */ 47 | u32 dir_ent_fname_off;/**< Offset of `struct dir_entry::name' */ 48 | 49 | /* 50 | * the following item(s) are only present in memory 51 | */ 52 | int sb_dev; /**< the super block's home device */ 53 | }; 54 | 55 | /** 56 | * @def SUPER_BLOCK_SIZE 57 | * @brief The size of super block \b in \b the \b device. 58 | * 59 | * Note that this is the size of the struct in the device, \b NOT in memory. 60 | * The size in memory is larger because of some more members. 61 | */ 62 | #define SUPER_BLOCK_SIZE 56 63 | 64 | /** 65 | * @struct inode 66 | * @brief i-node 67 | * 68 | * The \c start_sect and\c nr_sects locate the file in the device, 69 | * and the size show how many bytes is used. 70 | * If size < (nr_sects * SECTOR_SIZE) , the rest bytes 71 | * are wasted and reserved for later writing. 72 | * 73 | * \b NOTE: Remember to change INODE_SIZE if the members are changed 74 | */ 75 | struct inode { 76 | u32 i_mode; /**< Accsess mode */ 77 | u32 i_size; /**< File size */ 78 | u32 i_start_sect; /**< The first sector of the data */ 79 | u32 i_nr_sects; /**< How many sectors the file occupies */ 80 | u8 _unused[16]; /**< Stuff for alignment */ 81 | 82 | /* the following items are only present in memory */ 83 | int i_dev; 84 | int i_cnt; /**< How many procs share this inode */ 85 | int i_num; /**< inode nr. */ 86 | }; 87 | 88 | /** 89 | * @def INODE_SIZE 90 | * @brief The size of i-node stored \b in \b the \b device. 91 | * 92 | * Note that this is the size of the struct in the device, \b NOT in memory. 93 | * The size in memory is larger because of some more members. 94 | */ 95 | #define INODE_SIZE 32 96 | 97 | /** 98 | * @def MAX_FILENAME_LEN 99 | * @brief Max len of a filename 100 | * @see dir_entry 101 | */ 102 | #define MAX_FILENAME_LEN 12 103 | 104 | /** 105 | * @struct dir_entry 106 | * @brief Directory Entry 107 | */ 108 | struct dir_entry { 109 | int inode_nr; /**< inode nr. */ 110 | char name[MAX_FILENAME_LEN]; /**< Filename */ 111 | }; 112 | 113 | /** 114 | * @def DIR_ENTRY_SIZE 115 | * @brief The size of directory entry in the device. 116 | * 117 | * It is as same as the size in memory. 118 | */ 119 | #define DIR_ENTRY_SIZE sizeof(struct dir_entry) 120 | 121 | /** 122 | * @struct file_desc 123 | * @brief File Descriptor 124 | */ 125 | struct file_desc { 126 | int fd_mode; /**< R or W */ 127 | int fd_pos; /**< Current position for R/W. */ 128 | int fd_cnt; /**< How many procs share this desc */ 129 | struct inode* fd_inode; /**< Ptr to the i-node */ 130 | }; 131 | 132 | 133 | /** 134 | * Since all invocations of `rw_sector()' in FS look similar (most of the 135 | * params are the same), we use this macro to make code more readable. 136 | */ 137 | #define RD_SECT(dev,sect_nr) rw_sector(DEV_READ, \ 138 | dev, \ 139 | (sect_nr) * SECTOR_SIZE, \ 140 | SECTOR_SIZE, /* read one sector */ \ 141 | TASK_FS, \ 142 | fsbuf); 143 | #define WR_SECT(dev,sect_nr) rw_sector(DEV_WRITE, \ 144 | dev, \ 145 | (sect_nr) * SECTOR_SIZE, \ 146 | SECTOR_SIZE, /* write one sector */ \ 147 | TASK_FS, \ 148 | fsbuf); 149 | 150 | 151 | #endif /* _ORANGES_FS_H_ */ 152 | -------------------------------------------------------------------------------- /include/sys/global.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | global.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | /* EXTERN is defined as extern except in global.c */ 9 | #ifdef GLOBAL_VARIABLES_HERE 10 | #undef EXTERN 11 | #define EXTERN 12 | #endif 13 | 14 | EXTERN int ticks; 15 | 16 | EXTERN int disp_pos; 17 | 18 | EXTERN u8 gdt_ptr[6]; /* 0~15:Limit 16~47:Base */ 19 | EXTERN struct descriptor gdt[GDT_SIZE]; 20 | EXTERN u8 idt_ptr[6]; /* 0~15:Limit 16~47:Base */ 21 | EXTERN struct gate idt[IDT_SIZE]; 22 | 23 | EXTERN u32 k_reenter; 24 | EXTERN int current_console; 25 | 26 | EXTERN int key_pressed; /** 27 | * used for clock_handler 28 | * to wake up TASK_TTY when 29 | * a key is pressed 30 | */ 31 | 32 | EXTERN struct tss tss; 33 | EXTERN struct proc* p_proc_ready; 34 | 35 | extern char task_stack[]; 36 | extern struct proc proc_table[]; 37 | extern struct task task_table[]; 38 | extern struct task user_proc_table[]; 39 | extern irq_handler irq_table[]; 40 | extern TTY tty_table[]; 41 | extern CONSOLE console_table[]; 42 | 43 | /* MM */ 44 | EXTERN MESSAGE mm_msg; 45 | extern u8 * mmbuf; 46 | extern const int MMBUF_SIZE; 47 | EXTERN int memory_size; 48 | 49 | /* FS */ 50 | EXTERN struct file_desc f_desc_table[NR_FILE_DESC]; 51 | EXTERN struct inode inode_table[NR_INODE]; 52 | EXTERN struct super_block super_block[NR_SUPER_BLOCK]; 53 | extern u8 * fsbuf; 54 | extern const int FSBUF_SIZE; 55 | EXTERN MESSAGE fs_msg; 56 | EXTERN struct proc * pcaller; 57 | EXTERN struct inode * root_inode; 58 | extern struct dev_drv_map dd_map[]; 59 | 60 | /* for test only */ 61 | extern char * logbuf; 62 | extern const int LOGBUF_SIZE; 63 | extern char * logdiskbuf; 64 | extern const int LOGDISKBUF_SIZE; 65 | -------------------------------------------------------------------------------- /include/sys/keyboard.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | keyboard.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, December, 2003 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | #ifndef _ORANGES_KEYBOARD_H_ 9 | #define _ORANGES_KEYBOARD_H_ 10 | 11 | 12 | /************************************************************************/ 13 | /* Macros Declaration */ 14 | /************************************************************************/ 15 | #define KB_IN_BYTES 32 /* size of keyboard input buffer */ 16 | #define MAP_COLS 3 /* Number of columns in keymap */ 17 | #define NR_SCAN_CODES 0x80 /* Number of scan codes (rows in keymap) */ 18 | 19 | #define FLAG_BREAK 0x0080 /* Break Code */ 20 | #define FLAG_EXT 0x0100 /* Normal function keys */ 21 | #define FLAG_SHIFT_L 0x0200 /* Shift key */ 22 | #define FLAG_SHIFT_R 0x0400 /* Shift key */ 23 | #define FLAG_CTRL_L 0x0800 /* Control key */ 24 | #define FLAG_CTRL_R 0x1000 /* Control key */ 25 | #define FLAG_ALT_L 0x2000 /* Alternate key */ 26 | #define FLAG_ALT_R 0x4000 /* Alternate key */ 27 | #define FLAG_PAD 0x8000 /* keys in num pad */ 28 | 29 | #define MASK_RAW 0x01FF /* raw key value = code passed to tty & MASK_RAW 30 | the value can be found either in the keymap column 0 31 | or in the list below */ 32 | 33 | /* Special keys */ 34 | #define ESC (0x01 + FLAG_EXT) /* Esc */ 35 | #define TAB (0x02 + FLAG_EXT) /* Tab */ 36 | #define ENTER (0x03 + FLAG_EXT) /* Enter */ 37 | #define BACKSPACE (0x04 + FLAG_EXT) /* BackSpace */ 38 | 39 | #define GUI_L (0x05 + FLAG_EXT) /* L GUI */ 40 | #define GUI_R (0x06 + FLAG_EXT) /* R GUI */ 41 | #define APPS (0x07 + FLAG_EXT) /* APPS */ 42 | 43 | /* Shift, Ctrl, Alt */ 44 | #define SHIFT_L (0x08 + FLAG_EXT) /* L Shift */ 45 | #define SHIFT_R (0x09 + FLAG_EXT) /* R Shift */ 46 | #define CTRL_L (0x0A + FLAG_EXT) /* L Ctrl */ 47 | #define CTRL_R (0x0B + FLAG_EXT) /* R Ctrl */ 48 | #define ALT_L (0x0C + FLAG_EXT) /* L Alt */ 49 | #define ALT_R (0x0D + FLAG_EXT) /* R Alt */ 50 | 51 | /* Lock keys */ 52 | #define CAPS_LOCK (0x0E + FLAG_EXT) /* Caps Lock */ 53 | #define NUM_LOCK (0x0F + FLAG_EXT) /* Number Lock */ 54 | #define SCROLL_LOCK (0x10 + FLAG_EXT) /* Scroll Lock */ 55 | 56 | /* Function keys */ 57 | #define F1 (0x11 + FLAG_EXT) /* F1 */ 58 | #define F2 (0x12 + FLAG_EXT) /* F2 */ 59 | #define F3 (0x13 + FLAG_EXT) /* F3 */ 60 | #define F4 (0x14 + FLAG_EXT) /* F4 */ 61 | #define F5 (0x15 + FLAG_EXT) /* F5 */ 62 | #define F6 (0x16 + FLAG_EXT) /* F6 */ 63 | #define F7 (0x17 + FLAG_EXT) /* F7 */ 64 | #define F8 (0x18 + FLAG_EXT) /* F8 */ 65 | #define F9 (0x19 + FLAG_EXT) /* F9 */ 66 | #define F10 (0x1A + FLAG_EXT) /* F10 */ 67 | #define F11 (0x1B + FLAG_EXT) /* F11 */ 68 | #define F12 (0x1C + FLAG_EXT) /* F12 */ 69 | 70 | /* Control Pad */ 71 | #define PRINTSCREEN (0x1D + FLAG_EXT) /* Print Screen */ 72 | #define PAUSEBREAK (0x1E + FLAG_EXT) /* Pause/Break */ 73 | #define INSERT (0x1F + FLAG_EXT) /* Insert */ 74 | #define DELETE (0x20 + FLAG_EXT) /* Delete */ 75 | #define HOME (0x21 + FLAG_EXT) /* Home */ 76 | #define END (0x22 + FLAG_EXT) /* End */ 77 | #define PAGEUP (0x23 + FLAG_EXT) /* Page Up */ 78 | #define PAGEDOWN (0x24 + FLAG_EXT) /* Page Down */ 79 | #define UP (0x25 + FLAG_EXT) /* Up */ 80 | #define DOWN (0x26 + FLAG_EXT) /* Down */ 81 | #define LEFT (0x27 + FLAG_EXT) /* Left */ 82 | #define RIGHT (0x28 + FLAG_EXT) /* Right */ 83 | 84 | /* ACPI keys */ 85 | #define POWER (0x29 + FLAG_EXT) /* Power */ 86 | #define SLEEP (0x2A + FLAG_EXT) /* Sleep */ 87 | #define WAKE (0x2B + FLAG_EXT) /* Wake Up */ 88 | 89 | /* Num Pad */ 90 | #define PAD_SLASH (0x2C + FLAG_EXT) /* / */ 91 | #define PAD_STAR (0x2D + FLAG_EXT) /* * */ 92 | #define PAD_MINUS (0x2E + FLAG_EXT) /* - */ 93 | #define PAD_PLUS (0x2F + FLAG_EXT) /* + */ 94 | #define PAD_ENTER (0x30 + FLAG_EXT) /* Enter */ 95 | #define PAD_DOT (0x31 + FLAG_EXT) /* . */ 96 | #define PAD_0 (0x32 + FLAG_EXT) /* 0 */ 97 | #define PAD_1 (0x33 + FLAG_EXT) /* 1 */ 98 | #define PAD_2 (0x34 + FLAG_EXT) /* 2 */ 99 | #define PAD_3 (0x35 + FLAG_EXT) /* 3 */ 100 | #define PAD_4 (0x36 + FLAG_EXT) /* 4 */ 101 | #define PAD_5 (0x37 + FLAG_EXT) /* 5 */ 102 | #define PAD_6 (0x38 + FLAG_EXT) /* 6 */ 103 | #define PAD_7 (0x39 + FLAG_EXT) /* 7 */ 104 | #define PAD_8 (0x3A + FLAG_EXT) /* 8 */ 105 | #define PAD_9 (0x3B + FLAG_EXT) /* 9 */ 106 | #define PAD_UP PAD_8 /* Up */ 107 | #define PAD_DOWN PAD_2 /* Down */ 108 | #define PAD_LEFT PAD_4 /* Left */ 109 | #define PAD_RIGHT PAD_6 /* Right */ 110 | #define PAD_HOME PAD_7 /* Home */ 111 | #define PAD_END PAD_1 /* End */ 112 | #define PAD_PAGEUP PAD_9 /* Page Up */ 113 | #define PAD_PAGEDOWN PAD_3 /* Page Down */ 114 | #define PAD_INS PAD_0 /* Ins */ 115 | #define PAD_MID PAD_5 /* Middle key */ 116 | #define PAD_DEL PAD_DOT /* Del */ 117 | 118 | 119 | /************************************************************************/ 120 | /* Stucture Definition */ 121 | /************************************************************************/ 122 | /* Keyboard structure, 1 per console. */ 123 | struct kb_inbuf { 124 | char* p_head; /* 指向缓冲区中下一个空闲位置 */ 125 | char* p_tail; /* 指向键盘任务应处理的字节 */ 126 | int count; /* 缓冲区中共有多少字节 */ 127 | char buf[KB_IN_BYTES]; /* 缓冲区 */ 128 | }; 129 | 130 | 131 | 132 | #endif /* _ORANGES_KEYBOARD_H_ */ 133 | -------------------------------------------------------------------------------- /include/sys/keymap.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | keymap.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, January, 2004 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | /********************************************************************/ 9 | /* "scan code" <--> "key" map. */ 10 | /* It should be and can only be included by keyboard.c! */ 11 | /********************************************************************/ 12 | 13 | #ifndef _ORANGES_KEYMAP_H_ 14 | #define _ORANGES_KEYMAP_H_ 15 | 16 | 17 | /* Keymap for US MF-2 keyboard. */ 18 | 19 | u32 keymap[NR_SCAN_CODES * MAP_COLS] = { 20 | 21 | /* scan-code !Shift Shift E0 XX */ 22 | /* ==================================================================== */ 23 | /* 0x00 - none */ 0, 0, 0, 24 | /* 0x01 - ESC */ ESC, ESC, 0, 25 | /* 0x02 - '1' */ '1', '!', 0, 26 | /* 0x03 - '2' */ '2', '@', 0, 27 | /* 0x04 - '3' */ '3', '#', 0, 28 | /* 0x05 - '4' */ '4', '$', 0, 29 | /* 0x06 - '5' */ '5', '%', 0, 30 | /* 0x07 - '6' */ '6', '^', 0, 31 | /* 0x08 - '7' */ '7', '&', 0, 32 | /* 0x09 - '8' */ '8', '*', 0, 33 | /* 0x0A - '9' */ '9', '(', 0, 34 | /* 0x0B - '0' */ '0', ')', 0, 35 | /* 0x0C - '-' */ '-', '_', 0, 36 | /* 0x0D - '=' */ '=', '+', 0, 37 | /* 0x0E - BS */ BACKSPACE, BACKSPACE, 0, 38 | /* 0x0F - TAB */ TAB, TAB, 0, 39 | /* 0x10 - 'q' */ 'q', 'Q', 0, 40 | /* 0x11 - 'w' */ 'w', 'W', 0, 41 | /* 0x12 - 'e' */ 'e', 'E', 0, 42 | /* 0x13 - 'r' */ 'r', 'R', 0, 43 | /* 0x14 - 't' */ 't', 'T', 0, 44 | /* 0x15 - 'y' */ 'y', 'Y', 0, 45 | /* 0x16 - 'u' */ 'u', 'U', 0, 46 | /* 0x17 - 'i' */ 'i', 'I', 0, 47 | /* 0x18 - 'o' */ 'o', 'O', 0, 48 | /* 0x19 - 'p' */ 'p', 'P', 0, 49 | /* 0x1A - '[' */ '[', '{', 0, 50 | /* 0x1B - ']' */ ']', '}', 0, 51 | /* 0x1C - CR/LF */ ENTER, ENTER, PAD_ENTER, 52 | /* 0x1D - l. Ctrl */ CTRL_L, CTRL_L, CTRL_R, 53 | /* 0x1E - 'a' */ 'a', 'A', 0, 54 | /* 0x1F - 's' */ 's', 'S', 0, 55 | /* 0x20 - 'd' */ 'd', 'D', 0, 56 | /* 0x21 - 'f' */ 'f', 'F', 0, 57 | /* 0x22 - 'g' */ 'g', 'G', 0, 58 | /* 0x23 - 'h' */ 'h', 'H', 0, 59 | /* 0x24 - 'j' */ 'j', 'J', 0, 60 | /* 0x25 - 'k' */ 'k', 'K', 0, 61 | /* 0x26 - 'l' */ 'l', 'L', 0, 62 | /* 0x27 - ';' */ ';', ':', 0, 63 | /* 0x28 - '\'' */ '\'', '"', 0, 64 | /* 0x29 - '`' */ '`', '~', 0, 65 | /* 0x2A - l. SHIFT */ SHIFT_L, SHIFT_L, 0, 66 | /* 0x2B - '\' */ '\\', '|', 0, 67 | /* 0x2C - 'z' */ 'z', 'Z', 0, 68 | /* 0x2D - 'x' */ 'x', 'X', 0, 69 | /* 0x2E - 'c' */ 'c', 'C', 0, 70 | /* 0x2F - 'v' */ 'v', 'V', 0, 71 | /* 0x30 - 'b' */ 'b', 'B', 0, 72 | /* 0x31 - 'n' */ 'n', 'N', 0, 73 | /* 0x32 - 'm' */ 'm', 'M', 0, 74 | /* 0x33 - ',' */ ',', '<', 0, 75 | /* 0x34 - '.' */ '.', '>', 0, 76 | /* 0x35 - '/' */ '/', '?', PAD_SLASH, 77 | /* 0x36 - r. SHIFT */ SHIFT_R, SHIFT_R, 0, 78 | /* 0x37 - '*' */ '*', '*', 0, 79 | /* 0x38 - ALT */ ALT_L, ALT_L, ALT_R, 80 | /* 0x39 - ' ' */ ' ', ' ', 0, 81 | /* 0x3A - CapsLock */ CAPS_LOCK, CAPS_LOCK, 0, 82 | /* 0x3B - F1 */ F1, F1, 0, 83 | /* 0x3C - F2 */ F2, F2, 0, 84 | /* 0x3D - F3 */ F3, F3, 0, 85 | /* 0x3E - F4 */ F4, F4, 0, 86 | /* 0x3F - F5 */ F5, F5, 0, 87 | /* 0x40 - F6 */ F6, F6, 0, 88 | /* 0x41 - F7 */ F7, F7, 0, 89 | /* 0x42 - F8 */ F8, F8, 0, 90 | /* 0x43 - F9 */ F9, F9, 0, 91 | /* 0x44 - F10 */ F10, F10, 0, 92 | /* 0x45 - NumLock */ NUM_LOCK, NUM_LOCK, 0, 93 | /* 0x46 - ScrLock */ SCROLL_LOCK, SCROLL_LOCK, 0, 94 | /* 0x47 - Home */ PAD_HOME, '7', HOME, 95 | /* 0x48 - CurUp */ PAD_UP, '8', UP, 96 | /* 0x49 - PgUp */ PAD_PAGEUP, '9', PAGEUP, 97 | /* 0x4A - '-' */ PAD_MINUS, '-', 0, 98 | /* 0x4B - Left */ PAD_LEFT, '4', LEFT, 99 | /* 0x4C - MID */ PAD_MID, '5', 0, 100 | /* 0x4D - Right */ PAD_RIGHT, '6', RIGHT, 101 | /* 0x4E - '+' */ PAD_PLUS, '+', 0, 102 | /* 0x4F - End */ PAD_END, '1', END, 103 | /* 0x50 - Down */ PAD_DOWN, '2', DOWN, 104 | /* 0x51 - PgDown */ PAD_PAGEDOWN, '3', PAGEDOWN, 105 | /* 0x52 - Insert */ PAD_INS, '0', INSERT, 106 | /* 0x53 - Delete */ PAD_DOT, '.', DELETE, 107 | /* 0x54 - Enter */ 0, 0, 0, 108 | /* 0x55 - ??? */ 0, 0, 0, 109 | /* 0x56 - ??? */ 0, 0, 0, 110 | /* 0x57 - F11 */ F11, F11, 0, 111 | /* 0x58 - F12 */ F12, F12, 0, 112 | /* 0x59 - ??? */ 0, 0, 0, 113 | /* 0x5A - ??? */ 0, 0, 0, 114 | /* 0x5B - ??? */ 0, 0, GUI_L, 115 | /* 0x5C - ??? */ 0, 0, GUI_R, 116 | /* 0x5D - ??? */ 0, 0, APPS, 117 | /* 0x5E - ??? */ 0, 0, 0, 118 | /* 0x5F - ??? */ 0, 0, 0, 119 | /* 0x60 - ??? */ 0, 0, 0, 120 | /* 0x61 - ??? */ 0, 0, 0, 121 | /* 0x62 - ??? */ 0, 0, 0, 122 | /* 0x63 - ??? */ 0, 0, 0, 123 | /* 0x64 - ??? */ 0, 0, 0, 124 | /* 0x65 - ??? */ 0, 0, 0, 125 | /* 0x66 - ??? */ 0, 0, 0, 126 | /* 0x67 - ??? */ 0, 0, 0, 127 | /* 0x68 - ??? */ 0, 0, 0, 128 | /* 0x69 - ??? */ 0, 0, 0, 129 | /* 0x6A - ??? */ 0, 0, 0, 130 | /* 0x6B - ??? */ 0, 0, 0, 131 | /* 0x6C - ??? */ 0, 0, 0, 132 | /* 0x6D - ??? */ 0, 0, 0, 133 | /* 0x6E - ??? */ 0, 0, 0, 134 | /* 0x6F - ??? */ 0, 0, 0, 135 | /* 0x70 - ??? */ 0, 0, 0, 136 | /* 0x71 - ??? */ 0, 0, 0, 137 | /* 0x72 - ??? */ 0, 0, 0, 138 | /* 0x73 - ??? */ 0, 0, 0, 139 | /* 0x74 - ??? */ 0, 0, 0, 140 | /* 0x75 - ??? */ 0, 0, 0, 141 | /* 0x76 - ??? */ 0, 0, 0, 142 | /* 0x77 - ??? */ 0, 0, 0, 143 | /* 0x78 - ??? */ 0, 0, 0, 144 | /* 0x78 - ??? */ 0, 0, 0, 145 | /* 0x7A - ??? */ 0, 0, 0, 146 | /* 0x7B - ??? */ 0, 0, 0, 147 | /* 0x7C - ??? */ 0, 0, 0, 148 | /* 0x7D - ??? */ 0, 0, 0, 149 | /* 0x7E - ??? */ 0, 0, 0, 150 | /* 0x7F - ??? */ 0, 0, 0 151 | }; 152 | 153 | 154 | /* 155 | 回车键: 把光标移到第一列 156 | 换行键: 把光标前进到下一行 157 | */ 158 | 159 | 160 | /*====================================================================================* 161 | Appendix: Scan code set 1 162 | *====================================================================================* 163 | 164 | KEY MAKE BREAK ----- KEY MAKE BREAK ----- KEY MAKE BREAK 165 | -------------------------------------------------------------------------------------- 166 | A 1E 9E 9 0A 8A [ 1A 9A 167 | B 30 B0 ` 29 89 INSERT E0,52 E0,D2 168 | C 2E AE - 0C 8C HOME E0,47 E0,C7 169 | D 20 A0 = 0D 8D PG UP E0,49 E0,C9 170 | E 12 92 \ 2B AB DELETE E0,53 E0,D3 171 | F 21 A1 BKSP 0E 8E END E0,4F E0,CF 172 | G 22 A2 SPACE 39 B9 PG DN E0,51 E0,D1 173 | H 23 A3 TAB 0F 8F U ARROW E0,48 E0,C8 174 | I 17 97 CAPS 3A BA L ARROW E0,4B E0,CB 175 | J 24 A4 L SHFT 2A AA D ARROW E0,50 E0,D0 176 | K 25 A5 L CTRL 1D 9D R ARROW E0,4D E0,CD 177 | L 26 A6 L GUI E0,5B E0,DB NUM 45 C5 178 | M 32 B2 L ALT 38 B8 KP / E0,35 E0,B5 179 | N 31 B1 R SHFT 36 B6 KP * 37 B7 180 | O 18 98 R CTRL E0,1D E0,9D KP - 4A CA 181 | P 19 99 R GUI E0,5C E0,DC KP + 4E CE 182 | Q 10 19 R ALT E0,38 E0,B8 KP EN E0,1C E0,9C 183 | R 13 93 APPS E0,5D E0,DD KP . 53 D3 184 | S 1F 9F ENTER 1C 9C KP 0 52 D2 185 | T 14 94 ESC 01 81 KP 1 4F CF 186 | U 16 96 F1 3B BB KP 2 50 D0 187 | V 2F AF F2 3C BC KP 3 51 D1 188 | W 11 91 F3 3D BD KP 4 4B CB 189 | X 2D AD F4 3E BE KP 5 4C CC 190 | Y 15 95 F5 3F BF KP 6 4D CD 191 | Z 2C AC F6 40 C0 KP 7 47 C7 192 | 0 0B 8B F7 41 C1 KP 8 48 C8 193 | 1 02 82 F8 42 C2 KP 9 49 C9 194 | 2 03 83 F9 43 C3 ] 1B 9B 195 | 3 04 84 F10 44 C4 ; 27 A7 196 | 4 05 85 F11 57 D7 ' 28 A8 197 | 5 06 86 F12 58 D8 , 33 B3 198 | 199 | 6 07 87 PRTSCRN E0,2A E0,B7 . 34 B4 200 | E0,37 E0,AA 201 | 202 | 7 08 88 SCROLL 46 C6 / 35 B5 203 | 204 | 8 09 89 PAUSE E1,1D,45 -NONE- 205 | E1,9D,C5 206 | 207 | 208 | ----------------- 209 | ACPI Scan Codes: 210 | ------------------------------------------- 211 | Key Make Code Break Code 212 | ------------------------------------------- 213 | Power E0, 5E E0, DE 214 | Sleep E0, 5F E0, DF 215 | Wake E0, 63 E0, E3 216 | 217 | 218 | ------------------------------- 219 | Windows Multimedia Scan Codes: 220 | ------------------------------------------- 221 | Key Make Code Break Code 222 | ------------------------------------------- 223 | Next Track E0, 19 E0, 99 224 | Previous Track E0, 10 E0, 90 225 | Stop E0, 24 E0, A4 226 | Play/Pause E0, 22 E0, A2 227 | Mute E0, 20 E0, A0 228 | Volume Up E0, 30 E0, B0 229 | Volume Down E0, 2E E0, AE 230 | Media Select E0, 6D E0, ED 231 | E-Mail E0, 6C E0, EC 232 | Calculator E0, 21 E0, A1 233 | My Computer E0, 6B E0, EB 234 | WWW Search E0, 65 E0, E5 235 | WWW Home E0, 32 E0, B2 236 | WWW Back E0, 6A E0, EA 237 | WWW Forward E0, 69 E0, E9 238 | WWW Stop E0, 68 E0, E8 239 | WWW Refresh E0, 67 E0, E7 240 | WWW Favorites E0, 66 E0, E6 241 | 242 | *=====================================================================================*/ 243 | 244 | 245 | 246 | #endif /* _ORANGES_KEYMAP_H_ */ 247 | 248 | -------------------------------------------------------------------------------- /include/sys/proc.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | proc.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | 9 | struct stackframe { /* proc_ptr points here ↑ Low */ 10 | u32 gs; /* ┓ │ */ 11 | u32 fs; /* ┃ │ */ 12 | u32 es; /* ┃ │ */ 13 | u32 ds; /* ┃ │ */ 14 | u32 edi; /* ┃ │ */ 15 | u32 esi; /* ┣ pushed by save() │ */ 16 | u32 ebp; /* ┃ │ */ 17 | u32 kernel_esp; /* <- 'popad' will ignore it │ */ 18 | u32 ebx; /* ┃ ↑栈从高地址往低地址增长*/ 19 | u32 edx; /* ┃ │ */ 20 | u32 ecx; /* ┃ │ */ 21 | u32 eax; /* ┛ │ */ 22 | u32 retaddr; /* return address for assembly code save() │ */ 23 | u32 eip; /* ┓ │ */ 24 | u32 cs; /* ┃ │ */ 25 | u32 eflags; /* ┣ these are pushed by CPU during interrupt │ */ 26 | u32 esp; /* ┃ │ */ 27 | u32 ss; /* ┛ ┷High */ 28 | }; 29 | 30 | 31 | struct proc { 32 | struct stackframe regs; /* process registers saved in stack frame */ 33 | 34 | u16 ldt_sel; /* gdt selector giving ldt base and limit */ 35 | struct descriptor ldts[LDT_SIZE]; /* local descs for code and data */ 36 | 37 | int ticks; /* remained ticks */ 38 | int priority; 39 | 40 | /* u32 pid; /\* process id passed in from MM *\/ */ 41 | char name[16]; /* name of the process */ 42 | 43 | int p_flags; /** 44 | * process flags. 45 | * A proc is runnable iff p_flags==0 46 | */ 47 | 48 | MESSAGE * p_msg; 49 | int p_recvfrom; 50 | int p_sendto; 51 | 52 | int has_int_msg; /** 53 | * nonzero if an INTERRUPT occurred when 54 | * the task is not ready to deal with it. 55 | */ 56 | 57 | struct proc * q_sending; /** 58 | * queue of procs sending messages to 59 | * this proc 60 | */ 61 | struct proc * next_sending;/** 62 | * next proc in the sending 63 | * queue (q_sending) 64 | */ 65 | 66 | int p_parent; /**< pid of parent process */ 67 | 68 | int exit_status; /**< for parent */ 69 | 70 | struct file_desc * filp[NR_FILES]; 71 | }; 72 | 73 | struct task { 74 | task_f initial_eip; 75 | int stacksize; 76 | char name[32]; 77 | }; 78 | 79 | #define proc2pid(x) (x - proc_table) 80 | 81 | /* Number of tasks & processes */ 82 | #define NR_TASKS 5 83 | #define NR_PROCS 32 84 | #define NR_NATIVE_PROCS 4 85 | #define FIRST_PROC proc_table[0] 86 | #define LAST_PROC proc_table[NR_TASKS + NR_PROCS - 1] 87 | 88 | /** 89 | * All forked proc will use memory above PROCS_BASE. 90 | * 91 | * @attention make sure PROCS_BASE is higher than any buffers, such as 92 | * fsbuf, mmbuf, etc 93 | * @see global.c 94 | * @see global.h 95 | */ 96 | #define PROCS_BASE 0xA00000 /* 10 MB */ 97 | #define PROC_IMAGE_SIZE_DEFAULT 0x100000 /* 1 MB */ 98 | #define PROC_ORIGIN_STACK 0x400 /* 1 KB */ 99 | 100 | /* stacks of tasks */ 101 | #define STACK_SIZE_DEFAULT 0x4000 /* 16 KB */ 102 | #define STACK_SIZE_TTY STACK_SIZE_DEFAULT 103 | #define STACK_SIZE_SYS STACK_SIZE_DEFAULT 104 | #define STACK_SIZE_HD STACK_SIZE_DEFAULT 105 | #define STACK_SIZE_FS STACK_SIZE_DEFAULT 106 | #define STACK_SIZE_MM STACK_SIZE_DEFAULT 107 | #define STACK_SIZE_INIT STACK_SIZE_DEFAULT 108 | #define STACK_SIZE_TESTA STACK_SIZE_DEFAULT 109 | #define STACK_SIZE_TESTB STACK_SIZE_DEFAULT 110 | #define STACK_SIZE_TESTC STACK_SIZE_DEFAULT 111 | 112 | #define STACK_SIZE_TOTAL (STACK_SIZE_TTY + \ 113 | STACK_SIZE_SYS + \ 114 | STACK_SIZE_HD + \ 115 | STACK_SIZE_FS + \ 116 | STACK_SIZE_MM + \ 117 | STACK_SIZE_INIT + \ 118 | STACK_SIZE_TESTA + \ 119 | STACK_SIZE_TESTB + \ 120 | STACK_SIZE_TESTC) 121 | 122 | -------------------------------------------------------------------------------- /include/sys/protect.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | protect.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | #ifndef _ORANGES_PROTECT_H_ 9 | #define _ORANGES_PROTECT_H_ 10 | 11 | 12 | /* 存储段描述符/系统段描述符 */ 13 | struct descriptor /* 共 8 个字节 */ 14 | { 15 | u16 limit_low; /* Limit */ 16 | u16 base_low; /* Base */ 17 | u8 base_mid; /* Base */ 18 | u8 attr1; /* P(1) DPL(2) DT(1) TYPE(4) */ 19 | u8 limit_high_attr2; /* G(1) D(1) 0(1) AVL(1) LimitHigh(4) */ 20 | u8 base_high; /* Base */ 21 | }; 22 | 23 | #define reassembly(high, high_shift, mid, mid_shift, low) \ 24 | (((high) << (high_shift)) + \ 25 | ((mid) << (mid_shift)) + \ 26 | (low)) 27 | 28 | /* 门描述符 */ 29 | struct gate 30 | { 31 | u16 offset_low; /* Offset Low */ 32 | u16 selector; /* Selector */ 33 | u8 dcount; /* 该字段只在调用门描述符中有效。 34 | 如果在利用调用门调用子程序时引起特权级的转换和堆栈的改变,需要将外层堆栈中的参数复制到内层堆栈。 35 | 该双字计数字段就是用于说明这种情况发生时,要复制的双字参数的数量。 */ 36 | u8 attr; /* P(1) DPL(2) DT(1) TYPE(4) */ 37 | u16 offset_high; /* Offset High */ 38 | }; 39 | 40 | struct tss { 41 | u32 backlink; 42 | u32 esp0; /* stack pointer to use during interrupt */ 43 | u32 ss0; /* " segment " " " " */ 44 | u32 esp1; 45 | u32 ss1; 46 | u32 esp2; 47 | u32 ss2; 48 | u32 cr3; 49 | u32 eip; 50 | u32 flags; 51 | u32 eax; 52 | u32 ecx; 53 | u32 edx; 54 | u32 ebx; 55 | u32 esp; 56 | u32 ebp; 57 | u32 esi; 58 | u32 edi; 59 | u32 es; 60 | u32 cs; 61 | u32 ss; 62 | u32 ds; 63 | u32 fs; 64 | u32 gs; 65 | u32 ldt; 66 | u16 trap; 67 | u16 iobase; /* I/O位图基址大于或等于TSS段界限,就表示没有I/O许可位图 */ 68 | /*u8 iomap[2];*/ 69 | }; 70 | 71 | /* GDT */ 72 | /* 描述符索引 */ 73 | #define INDEX_DUMMY 0 /* ┓ */ 74 | #define INDEX_FLAT_C 1 /* ┣ LOADER 里面已经确定了的. */ 75 | #define INDEX_FLAT_RW 2 /* ┃ */ 76 | #define INDEX_VIDEO 3 /* ┛ */ 77 | #define INDEX_TSS 4 78 | #define INDEX_LDT_FIRST 5 79 | /* 选择子 */ 80 | #define SELECTOR_DUMMY 0 /* ┓ */ 81 | #define SELECTOR_FLAT_C 0x08 /* ┣ LOADER 里面已经确定了的. */ 82 | #define SELECTOR_FLAT_RW 0x10 /* ┃ */ 83 | #define SELECTOR_VIDEO (0x18+3) /* ┛<-- RPL=3 */ 84 | #define SELECTOR_TSS 0x20 /* TSS. 从外层跳到内存时 SS 和 ESP 的值从里面获得. */ 85 | #define SELECTOR_LDT_FIRST 0x28 86 | 87 | #define SELECTOR_KERNEL_CS SELECTOR_FLAT_C 88 | #define SELECTOR_KERNEL_DS SELECTOR_FLAT_RW 89 | #define SELECTOR_KERNEL_GS SELECTOR_VIDEO 90 | 91 | /* 每个任务有一个单独的 LDT, 每个 LDT 中的描述符个数: */ 92 | #define LDT_SIZE 2 93 | /* descriptor indices in LDT */ 94 | #define INDEX_LDT_C 0 95 | #define INDEX_LDT_RW 1 96 | 97 | /* 描述符类型值说明 */ 98 | #define DA_32 0x4000 /* 32 位段 */ 99 | #define DA_LIMIT_4K 0x8000 /* 段界限粒度为 4K 字节 */ 100 | #define LIMIT_4K_SHIFT 12 101 | #define DA_DPL0 0x00 /* DPL = 0 */ 102 | #define DA_DPL1 0x20 /* DPL = 1 */ 103 | #define DA_DPL2 0x40 /* DPL = 2 */ 104 | #define DA_DPL3 0x60 /* DPL = 3 */ 105 | /* 存储段描述符类型值说明 */ 106 | #define DA_DR 0x90 /* 存在的只读数据段类型值 */ 107 | #define DA_DRW 0x92 /* 存在的可读写数据段属性值 */ 108 | #define DA_DRWA 0x93 /* 存在的已访问可读写数据段类型值 */ 109 | #define DA_C 0x98 /* 存在的只执行代码段属性值 */ 110 | #define DA_CR 0x9A /* 存在的可执行可读代码段属性值 */ 111 | #define DA_CCO 0x9C /* 存在的只执行一致代码段属性值 */ 112 | #define DA_CCOR 0x9E /* 存在的可执行可读一致代码段属性值 */ 113 | /* 系统段描述符类型值说明 */ 114 | #define DA_LDT 0x82 /* 局部描述符表段类型值 */ 115 | #define DA_TaskGate 0x85 /* 任务门类型值 */ 116 | #define DA_386TSS 0x89 /* 可用 386 任务状态段类型值 */ 117 | #define DA_386CGate 0x8C /* 386 调用门类型值 */ 118 | #define DA_386IGate 0x8E /* 386 中断门类型值 */ 119 | #define DA_386TGate 0x8F /* 386 陷阱门类型值 */ 120 | 121 | /* 选择子类型值说明 */ 122 | /* 其中, SA_ : Selector Attribute */ 123 | #define SA_RPL_MASK 0xFFFC 124 | #define SA_RPL0 0 125 | #define SA_RPL1 1 126 | #define SA_RPL2 2 127 | #define SA_RPL3 3 128 | 129 | #define SA_TI_MASK 0xFFFB 130 | #define SA_TIG 0 131 | #define SA_TIL 4 132 | 133 | /* 中断向量 */ 134 | #define INT_VECTOR_DIVIDE 0x0 135 | #define INT_VECTOR_DEBUG 0x1 136 | #define INT_VECTOR_NMI 0x2 137 | #define INT_VECTOR_BREAKPOINT 0x3 138 | #define INT_VECTOR_OVERFLOW 0x4 139 | #define INT_VECTOR_BOUNDS 0x5 140 | #define INT_VECTOR_INVAL_OP 0x6 141 | #define INT_VECTOR_COPROC_NOT 0x7 142 | #define INT_VECTOR_DOUBLE_FAULT 0x8 143 | #define INT_VECTOR_COPROC_SEG 0x9 144 | #define INT_VECTOR_INVAL_TSS 0xA 145 | #define INT_VECTOR_SEG_NOT 0xB 146 | #define INT_VECTOR_STACK_FAULT 0xC 147 | #define INT_VECTOR_PROTECTION 0xD 148 | #define INT_VECTOR_PAGE_FAULT 0xE 149 | #define INT_VECTOR_COPROC_ERR 0x10 150 | 151 | /* 中断向量 */ 152 | #define INT_VECTOR_IRQ0 0x20 153 | #define INT_VECTOR_IRQ8 0x28 154 | 155 | /* 系统调用 */ 156 | #define INT_VECTOR_SYS_CALL 0x90 157 | 158 | /* 宏 */ 159 | /* 线性地址 → 物理地址 */ 160 | //#define vir2phys(seg_base, vir) (u32)(((u32)seg_base) + (u32)(vir)) 161 | 162 | /* seg:off -> linear addr */ 163 | #define makelinear(seg,off) (u32)(((u32)(seg2linear(seg))) + (u32)(off)) 164 | 165 | #endif /* _ORANGES_PROTECT_H_ */ 166 | -------------------------------------------------------------------------------- /include/sys/proto.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | proto.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | /* kliba.asm */ 9 | PUBLIC void out_byte(u16 port, u8 value); 10 | PUBLIC u8 in_byte(u16 port); 11 | PUBLIC void disp_str(char * info); 12 | PUBLIC void disp_color_str(char * info, int color); 13 | PUBLIC void disable_irq(int irq); 14 | PUBLIC void enable_irq(int irq); 15 | PUBLIC void disable_int(); 16 | PUBLIC void enable_int(); 17 | PUBLIC void port_read(u16 port, void* buf, int n); 18 | PUBLIC void port_write(u16 port, void* buf, int n); 19 | PUBLIC void glitter(int row, int col); 20 | 21 | /* string.asm */ 22 | PUBLIC char* strcpy(char* dst, const char* src); 23 | 24 | /* protect.c */ 25 | PUBLIC void init_prot(); 26 | PUBLIC u32 seg2linear(u16 seg); 27 | PUBLIC void init_desc(struct descriptor * p_desc, 28 | u32 base, u32 limit, u16 attribute); 29 | 30 | /* klib.c */ 31 | PUBLIC void get_boot_params(struct boot_params * pbp); 32 | PUBLIC int get_kernel_map(unsigned int * b, unsigned int * l); 33 | PUBLIC void delay(int time); 34 | PUBLIC void disp_int(int input); 35 | PUBLIC char * itoa(char * str, int num); 36 | 37 | /* kernel.asm */ 38 | PUBLIC void restart(); 39 | 40 | /* main.c */ 41 | PUBLIC void Init(); 42 | PUBLIC int get_ticks(); 43 | PUBLIC void TestA(); 44 | PUBLIC void TestB(); 45 | PUBLIC void TestC(); 46 | PUBLIC void panic(const char *fmt, ...); 47 | 48 | /* i8259.c */ 49 | PUBLIC void init_8259A(); 50 | PUBLIC void put_irq_handler(int irq, irq_handler handler); 51 | PUBLIC void spurious_irq(int irq); 52 | 53 | /* clock.c */ 54 | PUBLIC void clock_handler(int irq); 55 | PUBLIC void init_clock(); 56 | PUBLIC void milli_delay(int milli_sec); 57 | 58 | /* kernel/hd.c */ 59 | PUBLIC void task_hd(); 60 | PUBLIC void hd_handler(int irq); 61 | 62 | /* keyboard.c */ 63 | PUBLIC void init_keyboard(); 64 | PUBLIC void keyboard_read(TTY* p_tty); 65 | 66 | /* tty.c */ 67 | PUBLIC void task_tty(); 68 | PUBLIC void in_process(TTY* p_tty, u32 key); 69 | PUBLIC void dump_tty_buf(); /* for debug only */ 70 | 71 | /* systask.c */ 72 | PUBLIC void task_sys(); 73 | 74 | /* fs/main.c */ 75 | PUBLIC void task_fs(); 76 | PUBLIC int rw_sector(int io_type, int dev, u64 pos, 77 | int bytes, int proc_nr, void * buf); 78 | PUBLIC struct inode * get_inode(int dev, int num); 79 | PUBLIC void put_inode(struct inode * pinode); 80 | PUBLIC void sync_inode(struct inode * p); 81 | PUBLIC struct super_block * get_super_block(int dev); 82 | 83 | /* fs/open.c */ 84 | PUBLIC int do_open(); 85 | PUBLIC int do_close(); 86 | 87 | /* fs/read_write.c */ 88 | PUBLIC int do_rdwt(); 89 | 90 | /* fs/link.c */ 91 | PUBLIC int do_unlink(); 92 | 93 | /* fs/misc.c */ 94 | PUBLIC int do_stat(); 95 | PUBLIC int strip_path(char * filename, const char * pathname, 96 | struct inode** ppinode); 97 | PUBLIC int search_file(char * path); 98 | 99 | /* fs/disklog.c */ 100 | PUBLIC int do_disklog(); 101 | PUBLIC int disklog(char * logstr); /* for debug */ 102 | PUBLIC void dump_fd_graph(const char * fmt, ...); 103 | 104 | /* mm/main.c */ 105 | PUBLIC void task_mm(); 106 | PUBLIC int alloc_mem(int pid, int memsize); 107 | PUBLIC int free_mem(int pid); 108 | 109 | /* mm/forkexit.c */ 110 | PUBLIC int do_fork(); 111 | PUBLIC void do_exit(int status); 112 | PUBLIC void do_wait(); 113 | 114 | /* mm/exec.c */ 115 | PUBLIC int do_exec(); 116 | 117 | /* console.c */ 118 | PUBLIC void out_char(CONSOLE* p_con, char ch); 119 | PUBLIC void scroll_screen(CONSOLE* p_con, int direction); 120 | PUBLIC void select_console(int nr_console); 121 | PUBLIC void init_screen(TTY* p_tty); 122 | PUBLIC int is_current_console(CONSOLE* p_con); 123 | 124 | /* proc.c */ 125 | PUBLIC void schedule(); 126 | PUBLIC void* va2la(int pid, void* va); 127 | PUBLIC int ldt_seg_linear(struct proc* p, int idx); 128 | PUBLIC void reset_msg(MESSAGE* p); 129 | PUBLIC void dump_msg(const char * title, MESSAGE* m); 130 | PUBLIC void dump_proc(struct proc * p); 131 | PUBLIC int send_recv(int function, int src_dest, MESSAGE* msg); 132 | PUBLIC void inform_int(int task_nr); 133 | 134 | /* lib/misc.c */ 135 | PUBLIC void spin(char * func_name); 136 | 137 | /* 以下是系统调用相关 */ 138 | 139 | /* 系统调用 - 系统级 */ 140 | /* proc.c */ 141 | PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* m, struct proc* p); 142 | PUBLIC int sys_printx(int _unused1, int _unused2, char* s, struct proc * p_proc); 143 | 144 | /* syscall.asm */ 145 | PUBLIC void sys_call(); /* int_handler */ 146 | 147 | /* 系统调用 - 用户级 */ 148 | PUBLIC int sendrec(int function, int src_dest, MESSAGE* p_msg); 149 | PUBLIC int printx(char* str); 150 | -------------------------------------------------------------------------------- /include/sys/sconst.inc: -------------------------------------------------------------------------------- 1 | 2 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | ; sconst.inc 4 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | ; Forrest Yu, 2005 6 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | P_STACKBASE equ 0 9 | GSREG equ P_STACKBASE 10 | FSREG equ GSREG + 4 11 | ESREG equ FSREG + 4 12 | DSREG equ ESREG + 4 13 | EDIREG equ DSREG + 4 14 | ESIREG equ EDIREG + 4 15 | EBPREG equ ESIREG + 4 16 | KERNELESPREG equ EBPREG + 4 17 | EBXREG equ KERNELESPREG + 4 18 | EDXREG equ EBXREG + 4 19 | ECXREG equ EDXREG + 4 20 | EAXREG equ ECXREG + 4 21 | RETADR equ EAXREG + 4 22 | EIPREG equ RETADR + 4 23 | CSREG equ EIPREG + 4 24 | EFLAGSREG equ CSREG + 4 25 | ESPREG equ EFLAGSREG + 4 26 | SSREG equ ESPREG + 4 27 | P_STACKTOP equ SSREG + 4 28 | P_LDT_SEL equ P_STACKTOP 29 | P_LDT equ P_LDT_SEL + 4 30 | 31 | TSS3_S_SP0 equ 4 32 | 33 | INT_M_CTL equ 0x20 ; I/O port for interrupt controller 34 | INT_M_CTLMASK equ 0x21 ; setting bits in this port disables ints 35 | INT_S_CTL equ 0xA0 ; I/O port for second interrupt controller 36 | INT_S_CTLMASK equ 0xA1 ; setting bits in this port disables ints 37 | 38 | EOI equ 0x20 39 | 40 | ; 以下选择子值必须与 protect.h 中保持一致!!! 41 | SELECTOR_FLAT_C equ 0x08 ; LOADER 里面已经确定了的. 42 | SELECTOR_TSS equ 0x20 ; TSS. 从外层跳到内存时 SS 和 ESP 的值从里面获得. 43 | SELECTOR_KERNEL_CS equ SELECTOR_FLAT_C 44 | 45 | -------------------------------------------------------------------------------- /include/sys/tty.h: -------------------------------------------------------------------------------- 1 | 2 | /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | tty.h 4 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | Forrest Yu, 2005 6 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 7 | 8 | #ifndef _ORANGES_TTY_H_ 9 | #define _ORANGES_TTY_H_ 10 | 11 | 12 | #define TTY_IN_BYTES 256 /* tty input queue size */ 13 | #define TTY_OUT_BUF_LEN 2 /* tty output buffer size */ 14 | 15 | struct s_tty; 16 | struct s_console; 17 | 18 | /* TTY */ 19 | typedef struct s_tty 20 | { 21 | u32 ibuf[TTY_IN_BYTES]; /* TTY input buffer */ 22 | u32* ibuf_head; /* the next free slot */ 23 | u32* ibuf_tail; /* the val to be processed by TTY */ 24 | int ibuf_cnt; /* how many */ 25 | 26 | int tty_caller; 27 | int tty_procnr; 28 | void* tty_req_buf; 29 | int tty_left_cnt; 30 | int tty_trans_cnt; 31 | 32 | struct s_console * console; 33 | }TTY; 34 | 35 | #endif /* _ORANGES_TTY_H_ */ 36 | -------------------------------------------------------------------------------- /include/type.h: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #ifndef _ORANGES_TYPE_H_ 3 | #define _ORANGES_TYPE_H_ 4 | 5 | /* routine types */ 6 | #define PUBLIC /* PUBLIC is the opposite of PRIVATE */ 7 | #define PRIVATE static /* PRIVATE x limits the scope of x */ 8 | 9 | typedef unsigned long long u64; 10 | typedef unsigned int u32; 11 | typedef unsigned short u16; 12 | typedef unsigned char u8; 13 | 14 | typedef char * va_list; 15 | 16 | typedef void (*int_handler) (); 17 | typedef void (*task_f) (); 18 | typedef void (*irq_handler) (int irq); 19 | 20 | typedef void* system_call; 21 | 22 | 23 | /** 24 | * MESSAGE mechanism is borrowed from MINIX 25 | */ 26 | struct mess1 { 27 | int m1i1; 28 | int m1i2; 29 | int m1i3; 30 | int m1i4; 31 | }; 32 | struct mess2 { 33 | void* m2p1; 34 | void* m2p2; 35 | void* m2p3; 36 | void* m2p4; 37 | }; 38 | struct mess3 { 39 | int m3i1; 40 | int m3i2; 41 | int m3i3; 42 | int m3i4; 43 | u64 m3l1; 44 | u64 m3l2; 45 | void* m3p1; 46 | void* m3p2; 47 | }; 48 | typedef struct { 49 | int source; 50 | int type; 51 | union { 52 | struct mess1 m1; 53 | struct mess2 m2; 54 | struct mess3 m3; 55 | } u; 56 | } MESSAGE; 57 | 58 | /* i have no idea of where to put this struct, so i put it here */ 59 | struct boot_params { 60 | int mem_size; /* memory size */ 61 | unsigned char * kernel_file; /* addr of kernel file */ 62 | }; 63 | 64 | 65 | #endif /* _ORANGES_TYPE_H_ */ 66 | -------------------------------------------------------------------------------- /kernel.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/kernel.bin -------------------------------------------------------------------------------- /lib/NDKcore.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/NanoOS/993d1a8b11df45a741a0080d8eae422ff2daa0ee/lib/NDKcore.a -------------------------------------------------------------------------------- /lib/close.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | /***************************************************************************** 16 | * close 17 | *****************************************************************************/ 18 | /** 19 | * Close a file descriptor. 20 | * 21 | * @param fd File descriptor. 22 | * 23 | * @return Zero if successful, otherwise -1. 24 | *****************************************************************************/ 25 | PUBLIC int close(int fd) 26 | { 27 | MESSAGE msg; 28 | msg.type = CLOSE; 29 | msg.FD = fd; 30 | 31 | send_recv(BOTH, TASK_FS, &msg); 32 | 33 | return msg.RETVAL; 34 | } 35 | -------------------------------------------------------------------------------- /lib/color.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "color.h" 3 | /*懒得include*/ 4 | void disp_color_str(char * info, int color); 5 | 6 | /*打印INFO函数*/ 7 | void printfInfo() 8 | { 9 | disp_color_str("[INFO]\n",blackBrightGreenColor); 10 | } 11 | void printfWarn() 12 | { 13 | disp_color_str("[WARN]\n",blackYellowColor); 14 | } 15 | void printfErro() 16 | { 17 | disp_color_str("[ERRO]\n",blackBrightBrightRedColor); 18 | } 19 | /*打印INFO不回车*/ 20 | void printfInfoNotReturn() 21 | { 22 | disp_color_str("[INFO]",blackBrightGreenColor); 23 | } 24 | void printfWarnNotReturn() 25 | { 26 | disp_color_str("[WARN]",blackYellowColor); 27 | } 28 | void printfErroNotReturn() 29 | { 30 | disp_color_str("[ERRO]",blackBrightBrightRedColor); 31 | } -------------------------------------------------------------------------------- /lib/exec.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "type.h" 3 | #include "stdio.h" 4 | #include "const.h" 5 | #include "protect.h" 6 | #include "string.h" 7 | #include "fs.h" 8 | #include "proc.h" 9 | #include "tty.h" 10 | #include "console.h" 11 | #include "global.h" 12 | #include "proto.h" 13 | 14 | /***************************************************************************** 15 | * exec 16 | *****************************************************************************/ 17 | /** 18 | * Executes the program pointed by path. 19 | * 20 | * @param path The full path of the file to be executed. 21 | * 22 | * @return Zero if successful, otherwise -1. 23 | *****************************************************************************/ 24 | PUBLIC int exec(const char * path) 25 | { 26 | MESSAGE msg; 27 | msg.type = EXEC; 28 | msg.PATHNAME = (void*)path; 29 | msg.NAME_LEN = strlen(path); 30 | msg.BUF = 0; 31 | msg.BUF_LEN = 0; 32 | 33 | send_recv(BOTH, TASK_MM, &msg); 34 | assert(msg.type == SYSCALL_RET); 35 | 36 | return msg.RETVAL; 37 | } 38 | 39 | /***************************************************************************** 40 | * execl 41 | *****************************************************************************/ 42 | PUBLIC int execl(const char *path, const char *arg, ...) 43 | { 44 | va_list parg = (va_list)(&arg); 45 | char **p = (char**)parg; 46 | return execv(path, p); 47 | } 48 | 49 | /***************************************************************************** 50 | * execv 51 | *****************************************************************************/ 52 | PUBLIC int execv(const char *path, char * argv[]) 53 | { 54 | char **p = argv; 55 | char arg_stack[PROC_ORIGIN_STACK]; 56 | int stack_len = 0; 57 | 58 | while(*p++) { 59 | assert(stack_len + 2 * sizeof(char*) < PROC_ORIGIN_STACK); 60 | stack_len += sizeof(char*); 61 | } 62 | 63 | *((int*)(&arg_stack[stack_len])) = 0; 64 | stack_len += sizeof(char*); 65 | 66 | char ** q = (char**)arg_stack; 67 | for (p = argv; *p != 0; p++) { 68 | *q++ = &arg_stack[stack_len]; 69 | 70 | assert(stack_len + strlen(*p) + 1 < PROC_ORIGIN_STACK); 71 | strcpy(&arg_stack[stack_len], *p); 72 | stack_len += strlen(*p); 73 | arg_stack[stack_len] = 0; 74 | stack_len++; 75 | } 76 | 77 | MESSAGE msg; 78 | msg.type = EXEC; 79 | msg.PATHNAME = (void*)path; 80 | msg.NAME_LEN = strlen(path); 81 | msg.BUF = (void*)arg_stack; 82 | msg.BUF_LEN = stack_len; 83 | 84 | send_recv(BOTH, TASK_MM, &msg); 85 | assert(msg.type == SYSCALL_RET); 86 | 87 | return msg.RETVAL; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /lib/exit.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * exit 18 | *************************************************************************//** 19 | * Terminate the current process. 20 | * 21 | * @param status The value returned to the parent. 22 | *****************************************************************************/ 23 | PUBLIC void exit(int status) 24 | { 25 | MESSAGE msg; 26 | msg.type = EXIT; 27 | msg.STATUS = status; 28 | 29 | send_recv(BOTH, TASK_MM, &msg); 30 | assert(msg.type == SYSCALL_RET); 31 | } 32 | -------------------------------------------------------------------------------- /lib/fork.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * fork 18 | *****************************************************************************/ 19 | /** 20 | * Create a child process, which is actually a copy of the caller. 21 | * 22 | * @return On success, the PID of the child process is returned in the 23 | * parent's thread of execution, and a 0 is returned in the child's 24 | * thread of execution. 25 | * On failure, a -1 will be returned in the parent's context, no 26 | * child process will be created. 27 | *****************************************************************************/ 28 | PUBLIC int fork() 29 | { 30 | MESSAGE msg; 31 | msg.type = FORK; 32 | 33 | send_recv(BOTH, TASK_MM, &msg); 34 | assert(msg.type == SYSCALL_RET); 35 | assert(msg.RETVAL == 0); 36 | 37 | return msg.PID; 38 | } 39 | -------------------------------------------------------------------------------- /lib/getpid.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * getpid 18 | *****************************************************************************/ 19 | /** 20 | * Get the PID. 21 | * 22 | * @return The PID. 23 | *****************************************************************************/ 24 | PUBLIC int getpid() 25 | { 26 | MESSAGE msg; 27 | msg.type = GET_PID; 28 | 29 | send_recv(BOTH, TASK_SYS, &msg); 30 | assert(msg.type == SYSCALL_RET); 31 | 32 | return msg.PID; 33 | } 34 | -------------------------------------------------------------------------------- /lib/misc.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | /***************************************************************************** 17 | * send_recv 18 | *****************************************************************************/ 19 | /** 20 | * IPC syscall. 21 | * 22 | * It is an encapsulation of `sendrec', 23 | * invoking `sendrec' directly should be avoided 24 | * 25 | * @param function SEND, RECEIVE or BOTH 26 | * @param src_dest The caller's proc_nr 27 | * @param msg Pointer to the MESSAGE struct 28 | * 29 | * @return always 0. 30 | *****************************************************************************/ 31 | PUBLIC int send_recv(int function, int src_dest, MESSAGE* msg) 32 | { 33 | int ret = 0; 34 | 35 | if (function == RECEIVE) 36 | memset(msg, 0, sizeof(MESSAGE)); 37 | 38 | switch (function) { 39 | case BOTH: 40 | ret = sendrec(SEND, src_dest, msg); 41 | if (ret == 0) 42 | ret = sendrec(RECEIVE, src_dest, msg); 43 | break; 44 | case SEND: 45 | case RECEIVE: 46 | ret = sendrec(function, src_dest, msg); 47 | break; 48 | default: 49 | assert((function == BOTH) || 50 | (function == SEND) || (function == RECEIVE)); 51 | break; 52 | } 53 | 54 | return ret; 55 | } 56 | 57 | /***************************************************************************** 58 | * memcmp 59 | *****************************************************************************/ 60 | /** 61 | * Compare memory areas. 62 | * 63 | * @param s1 The 1st area. 64 | * @param s2 The 2nd area. 65 | * @param n The first n bytes will be compared. 66 | * 67 | * @return an integer less than, equal to, or greater than zero if the first 68 | * n bytes of s1 is found, respectively, to be less than, to match, 69 | * or be greater than the first n bytes of s2. 70 | *****************************************************************************/ 71 | PUBLIC int memcmp(const void * s1, const void *s2, int n) 72 | { 73 | if ((s1 == 0) || (s2 == 0)) { /* for robustness */ 74 | return (s1 - s2); 75 | } 76 | 77 | const char * p1 = (const char *)s1; 78 | const char * p2 = (const char *)s2; 79 | int i; 80 | for (i = 0; i < n; i++,p1++,p2++) { 81 | if (*p1 != *p2) { 82 | return (*p1 - *p2); 83 | } 84 | } 85 | return 0; 86 | } 87 | 88 | /***************************************************************************** 89 | * strcmp 90 | *****************************************************************************/ 91 | /** 92 | * Compare two strings. 93 | * 94 | * @param s1 The 1st string. 95 | * @param s2 The 2nd string. 96 | * 97 | * @return an integer less than, equal to, or greater than zero if s1 (or the 98 | * first n bytes thereof) is found, respectively, to be less than, 99 | * to match, or be greater than s2. 100 | *****************************************************************************/ 101 | PUBLIC int strcmp(const char * s1, const char *s2) 102 | { 103 | if ((s1 == 0) || (s2 == 0)) { /* for robustness */ 104 | return (s1 - s2); 105 | } 106 | 107 | const char * p1 = s1; 108 | const char * p2 = s2; 109 | 110 | for (; *p1 && *p2; p1++,p2++) { 111 | if (*p1 != *p2) { 112 | break; 113 | } 114 | } 115 | 116 | return (*p1 - *p2); 117 | } 118 | 119 | /***************************************************************************** 120 | * strcat 121 | *****************************************************************************/ 122 | /** 123 | * Concatenate two strings. 124 | * 125 | * @param s1 The 1st string. 126 | * @param s2 The 2nd string. 127 | * 128 | * @return Ptr to the 1st string. 129 | *****************************************************************************/ 130 | PUBLIC char * strcat(char * s1, const char *s2) 131 | { 132 | if ((s1 == 0) || (s2 == 0)) { /* for robustness */ 133 | return 0; 134 | } 135 | 136 | char * p1 = s1; 137 | for (; *p1; p1++) {} 138 | 139 | const char * p2 = s2; 140 | for (; *p2; p1++,p2++) { 141 | *p1 = *p2; 142 | } 143 | *p1 = 0; 144 | 145 | return s1; 146 | } 147 | 148 | /***************************************************************************** 149 | * spin 150 | *****************************************************************************/ 151 | PUBLIC void spin(char * func_name) 152 | { 153 | printl("\n[INFO][Core]spinning in %s ...\n", func_name); 154 | while (1) {} 155 | } 156 | 157 | 158 | /***************************************************************************** 159 | * assertion_failure 160 | *************************************************************************//** 161 | * Invoked by assert(). 162 | * 163 | * @param exp The failure expression itself. 164 | * @param file __FILE__ 165 | * @param base_file __BASE_FILE__ 166 | * @param line __LINE__ 167 | *****************************************************************************/ 168 | PUBLIC void assertion_failure(char *exp, char *file, char *base_file, int line) 169 | { 170 | printl("%c[ERRO][Core] assert(%s) failed: file: %s, base_file: %s, ln%d", 171 | MAG_CH_ASSERT, 172 | exp, file, base_file, line); 173 | 174 | /** 175 | * If assertion fails in a TASK, the system will halt before 176 | * printl() returns. If it happens in a USER PROC, printl() will 177 | * return like a common routine and arrive here. 178 | * @see sys_printx() 179 | * 180 | * We use a forever loop to prevent the proc from going on: 181 | */ 182 | spin("[ERRO][Core]assertion_failure()"); 183 | 184 | /* should never arrive here */ 185 | __asm__ __volatile__("ud2"); 186 | } 187 | -------------------------------------------------------------------------------- /lib/open.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | /***************************************************************************** 16 | * open 17 | *****************************************************************************/ 18 | /** 19 | * open/create a file. 20 | * 21 | * @param pathname The full path of the file to be opened/created. 22 | * @param flags O_CREAT, O_RDWR, etc. 23 | * 24 | * @return File descriptor if successful, otherwise -1. 25 | *****************************************************************************/ 26 | PUBLIC int open(const char *pathname, int flags) 27 | { 28 | MESSAGE msg; 29 | 30 | msg.type = OPEN; 31 | 32 | msg.PATHNAME = (void*)pathname; 33 | msg.FLAGS = flags; 34 | msg.NAME_LEN = strlen(pathname); 35 | 36 | send_recv(BOTH, TASK_FS, &msg); 37 | assert(msg.type == SYSCALL_RET); 38 | 39 | return msg.FD; 40 | } 41 | -------------------------------------------------------------------------------- /lib/printf.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | /****************************************************************************************** 17 | 可变参数函数调用原理(其中涉及的数字皆为举例) 18 | =========================================================================================== 19 | 20 | i = 0x23; 21 | j = 0x78; 22 | char fmt[] = "%x%d"; 23 | printf(fmt, i, j); 24 | 25 | push j 26 | push i 27 | push fmt 28 | call printf 29 | add esp, 3 * 4 30 | 31 | 32 | ┃ HIGH ┃ ┃ HIGH ┃ 33 | ┃ ... ┃ ┃ ... ┃ 34 | ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 35 | ┃ ┃ 0x32010┃ '\0' ┃ 36 | ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 37 | 0x3046C┃ 0x78 ┃ 0x3200c┃ d ┃ 38 | ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 39 | arg = 0x30468┃ 0x23 ┃ 0x32008┃ % ┃ 40 | ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 41 | 0x30464┃ 0x32000 ───╂────┐ 0x32004┃ x ┃ 42 | ┣━━━━━━━━━━┫ │ ┣━━━━━━━━━━┫ 43 | ┃ ┃ └──→ 0x32000┃ % ┃ 44 | ┣━━━━━━━━━━┫ ┣━━━━━━━━━━┫ 45 | ┃ ... ┃ ┃ ... ┃ 46 | ┃ LOW ┃ ┃ LOW ┃ 47 | 48 | 实际上,调用 vsprintf 的情形是这样的: 49 | 50 | vsprintf(buf, 0x32000, 0x30468); 51 | 52 | ******************************************************************************************/ 53 | 54 | /***************************************************************************** 55 | * printf 56 | *****************************************************************************/ 57 | /** 58 | * The most famous one. 59 | * 60 | * @note do not call me in any TASK, call me in USER PROC. 61 | * 62 | * @param fmt The format string 63 | * 64 | * @return The number of chars printed. 65 | *****************************************************************************/ 66 | PUBLIC int printf(const char *fmt, ...) 67 | { 68 | int i; 69 | char buf[STR_DEFAULT_LEN]; 70 | 71 | va_list arg = (va_list)((char*)(&fmt) + 4); /* 4 是参数 fmt 所占堆栈中的大小 */ 72 | i = vsprintf(buf, fmt, arg); 73 | int c = write(1, buf, i); 74 | 75 | assert(c == i); 76 | 77 | return i; 78 | } 79 | 80 | /***************************************************************************** 81 | * printl 82 | *****************************************************************************/ 83 | /** 84 | * low level print 85 | * 86 | * @param fmt The format string 87 | * 88 | * @return The number of chars printed. 89 | *****************************************************************************/ 90 | PUBLIC int printl(const char *fmt, ...) 91 | { 92 | int i; 93 | char buf[STR_DEFAULT_LEN]; 94 | 95 | va_list arg = (va_list)((char*)(&fmt) + 4); /** 96 | * 4: size of `fmt' in 97 | * the stack 98 | */ 99 | i = vsprintf(buf, fmt, arg); 100 | printx(buf); 101 | 102 | return i; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /lib/read.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | /***************************************************************************** 16 | * read 17 | *****************************************************************************/ 18 | /** 19 | * Read from a file descriptor. 20 | * 21 | * @param fd File descriptor. 22 | * @param buf Buffer to accept the bytes read. 23 | * @param count How many bytes to read. 24 | * 25 | * @return On success, the number of bytes read are returned. 26 | * On error, -1 is returned. 27 | *****************************************************************************/ 28 | PUBLIC int read(int fd, void *buf, int count) 29 | { 30 | MESSAGE msg; 31 | msg.type = READ; 32 | msg.FD = fd; 33 | msg.BUF = buf; 34 | msg.CNT = count; 35 | 36 | send_recv(BOTH, TASK_FS, &msg); 37 | 38 | return msg.CNT; 39 | } 40 | -------------------------------------------------------------------------------- /lib/stat.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * stat 18 | *************************************************************************//** 19 | * 20 | * 21 | * @param path 22 | * @param buf 23 | * 24 | * @return On success, zero is returned. On error, -1 is returned. 25 | *****************************************************************************/ 26 | PUBLIC int stat(const char *path, struct stat *buf) 27 | { 28 | MESSAGE msg; 29 | 30 | msg.type = STAT; 31 | 32 | msg.PATHNAME = (void*)path; 33 | msg.BUF = (void*)buf; 34 | msg.NAME_LEN = strlen(path); 35 | 36 | send_recv(BOTH, TASK_FS, &msg); 37 | assert(msg.type == SYSCALL_RET); 38 | 39 | return msg.RETVAL; 40 | } 41 | -------------------------------------------------------------------------------- /lib/string.asm: -------------------------------------------------------------------------------- 1 | 2 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | ; string.asm 4 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | ; Forrest Yu, 2005 6 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | [SECTION .text] 9 | 10 | ; 导出函数 11 | global memcpy 12 | global memset 13 | global strcpy 14 | global strlen 15 | 16 | 17 | ; ------------------------------------------------------------------------ 18 | ; void* memcpy(void* es:p_dst, void* ds:p_src, int size); 19 | ; ------------------------------------------------------------------------ 20 | memcpy: 21 | push ebp 22 | mov ebp, esp 23 | 24 | push esi 25 | push edi 26 | push ecx 27 | 28 | mov edi, [ebp + 8] ; Destination 29 | mov esi, [ebp + 12] ; Source 30 | mov ecx, [ebp + 16] ; Counter 31 | .1: 32 | cmp ecx, 0 ; 判断计数器 33 | jz .2 ; 计数器为零时跳出 34 | 35 | mov al, [ds:esi] ; ┓ 36 | inc esi ; ┃ 37 | ; ┣ 逐字节移动 38 | mov byte [es:edi], al ; ┃ 39 | inc edi ; ┛ 40 | 41 | dec ecx ; 计数器减一 42 | jmp .1 ; 循环 43 | .2: 44 | mov eax, [ebp + 8] ; 返回值 45 | 46 | pop ecx 47 | pop edi 48 | pop esi 49 | mov esp, ebp 50 | pop ebp 51 | 52 | ret ; 函数结束,返回 53 | ; memcpy 结束------------------------------------------------------------- 54 | 55 | 56 | ; ------------------------------------------------------------------------ 57 | ; void memset(void* p_dst, char ch, int size); 58 | ; ------------------------------------------------------------------------ 59 | memset: 60 | push ebp 61 | mov ebp, esp 62 | 63 | push esi 64 | push edi 65 | push ecx 66 | 67 | mov edi, [ebp + 8] ; Destination 68 | mov edx, [ebp + 12] ; Char to be putted 69 | mov ecx, [ebp + 16] ; Counter 70 | .1: 71 | cmp ecx, 0 ; 判断计数器 72 | jz .2 ; 计数器为零时跳出 73 | 74 | mov byte [edi], dl ; ┓ 75 | inc edi ; ┛ 76 | 77 | dec ecx ; 计数器减一 78 | jmp .1 ; 循环 79 | .2: 80 | 81 | pop ecx 82 | pop edi 83 | pop esi 84 | mov esp, ebp 85 | pop ebp 86 | 87 | ret ; 函数结束,返回 88 | ; ------------------------------------------------------------------------ 89 | 90 | 91 | ; ------------------------------------------------------------------------ 92 | ; char* strcpy(char* p_dst, char* p_src); 93 | ; ------------------------------------------------------------------------ 94 | strcpy: 95 | push ebp 96 | mov ebp, esp 97 | 98 | mov esi, [ebp + 12] ; Source 99 | mov edi, [ebp + 8] ; Destination 100 | 101 | .1: 102 | mov al, [esi] ; ┓ 103 | inc esi ; ┃ 104 | ; ┣ 逐字节移动 105 | mov byte [edi], al ; ┃ 106 | inc edi ; ┛ 107 | 108 | cmp al, 0 ; 是否遇到 '\0' 109 | jnz .1 ; 没遇到就继续循环,遇到就结束 110 | 111 | mov eax, [ebp + 8] ; 返回值 112 | 113 | pop ebp 114 | ret ; 函数结束,返回 115 | ; strcpy 结束------------------------------------------------------------- 116 | 117 | 118 | ; ------------------------------------------------------------------------ 119 | ; int strlen(char* p_str); 120 | ; ------------------------------------------------------------------------ 121 | strlen: 122 | push ebp 123 | mov ebp, esp 124 | 125 | mov eax, 0 ; 字符串长度开始是 0 126 | mov esi, [ebp + 8] ; esi 指向首地址 127 | 128 | .1: 129 | cmp byte [esi], 0 ; 看 esi 指向的字符是否是 '\0' 130 | jz .2 ; 如果是 '\0',程序结束 131 | inc esi ; 如果不是 '\0',esi 指向下一个字符 132 | inc eax ; 并且,eax 自加一 133 | jmp .1 ; 如此循环 134 | 135 | .2: 136 | pop ebp 137 | ret ; 函数结束,返回 138 | ; ------------------------------------------------------------------------ 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /lib/syscall.asm: -------------------------------------------------------------------------------- 1 | 2 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | ; syscall.asm 4 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 | ; Forrest Yu, 2005 6 | ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | %include "sconst.inc" 9 | 10 | INT_VECTOR_SYS_CALL equ 0x90 11 | _NR_printx equ 0 12 | _NR_sendrec equ 1 13 | 14 | ; 导出符号 15 | global printx 16 | global sendrec 17 | 18 | bits 32 19 | [section .text] 20 | 21 | ; ==================================================================================== 22 | ; sendrec(int function, int src_dest, MESSAGE* msg); 23 | ; ==================================================================================== 24 | ; Never call sendrec() directly, call send_recv() instead. 25 | sendrec: 26 | push ebx ; . 27 | push ecx ; > 12 bytes 28 | push edx ; / 29 | 30 | mov eax, _NR_sendrec 31 | mov ebx, [esp + 12 + 4] ; function 32 | mov ecx, [esp + 12 + 8] ; src_dest 33 | mov edx, [esp + 12 + 12] ; msg 34 | int INT_VECTOR_SYS_CALL 35 | 36 | pop edx 37 | pop ecx 38 | pop ebx 39 | 40 | ret 41 | 42 | ; ==================================================================================== 43 | ; void printx(char* s); 44 | ; ==================================================================================== 45 | printx: 46 | push edx ; 4 bytes 47 | 48 | mov eax, _NR_printx 49 | mov edx, [esp + 4 + 4] ; s 50 | int INT_VECTOR_SYS_CALL 51 | 52 | pop edx 53 | 54 | ret 55 | 56 | -------------------------------------------------------------------------------- /lib/syslog.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | 16 | /***************************************************************************** 17 | * syslog 18 | *****************************************************************************/ 19 | /** 20 | * Write log directly to the disk by sending message to FS. 21 | * 22 | * @param fmt The format string. 23 | * 24 | * @return How many chars have been printed. 25 | *****************************************************************************/ 26 | PUBLIC int syslog(const char *fmt, ...) 27 | { 28 | int i; 29 | char buf[STR_DEFAULT_LEN]; 30 | 31 | va_list arg = (va_list)((char*)(&fmt) + 4); /** 32 | * 4: size of `fmt' in 33 | * the stack 34 | */ 35 | i = vsprintf(buf, fmt, arg); 36 | assert(strlen(buf) == i); 37 | 38 | return disklog(buf); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /lib/unlink.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "type.h" 3 | #include "stdio.h" 4 | #include "const.h" 5 | #include "protect.h" 6 | #include "string.h" 7 | #include "fs.h" 8 | #include "proc.h" 9 | #include "tty.h" 10 | #include "console.h" 11 | #include "global.h" 12 | #include "proto.h" 13 | 14 | /***************************************************************************** 15 | * unlink 16 | *****************************************************************************/ 17 | /** 18 | * Delete a file. 19 | * 20 | * @param pathname The full path of the file to delete. 21 | * 22 | * @return Zero if successful, otherwise -1. 23 | *****************************************************************************/ 24 | PUBLIC int unlink(const char * pathname) 25 | { 26 | MESSAGE msg; 27 | msg.type = UNLINK; 28 | 29 | msg.PATHNAME = (void*)pathname; 30 | msg.NAME_LEN = strlen(pathname); 31 | 32 | send_recv(BOTH, TASK_FS, &msg); 33 | 34 | return msg.RETVAL; 35 | } 36 | -------------------------------------------------------------------------------- /lib/vsprintf.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | #include "type.h" 3 | #include "stdio.h" 4 | #include "const.h" 5 | #include "protect.h" 6 | #include "string.h" 7 | #include "fs.h" 8 | #include "proc.h" 9 | #include "tty.h" 10 | #include "console.h" 11 | #include "global.h" 12 | #include "keyboard.h" 13 | #include "proto.h" 14 | 15 | 16 | 17 | /*======================================================================* 18 | i2a 19 | *======================================================================*/ 20 | PRIVATE char* i2a(int val, int base, char ** ps) 21 | { 22 | int m = val % base; 23 | int q = val / base; 24 | if (q) { 25 | i2a(q, base, ps); 26 | } 27 | *(*ps)++ = (m < 10) ? (m + '0') : (m - 10 + 'A'); 28 | 29 | return *ps; 30 | } 31 | 32 | 33 | /*======================================================================* 34 | vsprintf 35 | *======================================================================*/ 36 | /* 37 | * 为更好地理解此函数的原理,可参考 printf 的注释部分。 38 | */ 39 | PUBLIC int vsprintf(char *buf, const char *fmt, va_list args) 40 | { 41 | char* p; 42 | 43 | va_list p_next_arg = args; 44 | int m; 45 | 46 | char inner_buf[STR_DEFAULT_LEN]; 47 | char cs; 48 | int align_nr; 49 | 50 | for (p=buf;*fmt;fmt++) { 51 | if (*fmt != '%') { 52 | *p++ = *fmt; 53 | continue; 54 | } 55 | else { /* a format string begins */ 56 | align_nr = 0; 57 | } 58 | 59 | fmt++; 60 | 61 | if (*fmt == '%') { 62 | *p++ = *fmt; 63 | continue; 64 | } 65 | else if (*fmt == '0') { 66 | cs = '0'; 67 | fmt++; 68 | } 69 | else { 70 | cs = ' '; 71 | } 72 | while (((unsigned char)(*fmt) >= '0') && ((unsigned char)(*fmt) <= '9')) { 73 | align_nr *= 10; 74 | align_nr += *fmt - '0'; 75 | fmt++; 76 | } 77 | 78 | char * q = inner_buf; 79 | memset(q, 0, sizeof(inner_buf)); 80 | 81 | switch (*fmt) { 82 | case 'c': 83 | *q++ = *((char*)p_next_arg); 84 | p_next_arg += 4; 85 | break; 86 | case 'x': 87 | m = *((int*)p_next_arg); 88 | i2a(m, 16, &q); 89 | p_next_arg += 4; 90 | break; 91 | case 'd': 92 | m = *((int*)p_next_arg); 93 | if (m < 0) { 94 | m = m * (-1); 95 | *q++ = '-'; 96 | } 97 | i2a(m, 10, &q); 98 | p_next_arg += 4; 99 | break; 100 | case 's': 101 | strcpy(q, (*((char**)p_next_arg))); 102 | q += strlen(*((char**)p_next_arg)); 103 | p_next_arg += 4; 104 | break; 105 | default: 106 | break; 107 | } 108 | 109 | int k; 110 | for (k = 0; k < ((align_nr > strlen(inner_buf)) ? (align_nr - strlen(inner_buf)) : 0); k++) { 111 | *p++ = cs; 112 | } 113 | q = inner_buf; 114 | while (*q) { 115 | *p++ = *q++; 116 | } 117 | } 118 | 119 | *p = 0; 120 | 121 | return (p - buf); 122 | } 123 | 124 | 125 | /*======================================================================* 126 | sprintf 127 | *======================================================================*/ 128 | int sprintf(char *buf, const char *fmt, ...) 129 | { 130 | va_list arg = (va_list)((char*)(&fmt) + 4); /* 4 是参数 fmt 所占堆栈中的大小 */ 131 | return vsprintf(buf, fmt, arg); 132 | } 133 | -------------------------------------------------------------------------------- /lib/wait.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | /***************************************************************************** 16 | * wait 17 | *****************************************************************************/ 18 | /** 19 | * Wait for the child process to terminiate. 20 | * 21 | * @param status The value returned from the child. 22 | * 23 | * @return PID of the terminated child. 24 | *****************************************************************************/ 25 | PUBLIC int wait(int * status) 26 | { 27 | MESSAGE msg; 28 | msg.type = WAIT; 29 | 30 | send_recv(BOTH, TASK_MM, &msg); 31 | 32 | *status = msg.STATUS; 33 | 34 | return (msg.PID == NO_TASK ? -1 : msg.PID); 35 | } 36 | -------------------------------------------------------------------------------- /lib/write.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "proto.h" 14 | 15 | /***************************************************************************** 16 | * write 17 | *****************************************************************************/ 18 | /** 19 | * Write to a file descriptor. 20 | * 21 | * @param fd File descriptor. 22 | * @param buf Buffer including the bytes to write. 23 | * @param count How many bytes to write. 24 | * 25 | * @return On success, the number of bytes written are returned. 26 | * On error, -1 is returned. 27 | *****************************************************************************/ 28 | PUBLIC int write(int fd, const void *buf, int count) 29 | { 30 | MESSAGE msg; 31 | msg.type = WRITE; 32 | msg.FD = fd; 33 | msg.BUF = (void*)buf; 34 | msg.CNT = count; 35 | 36 | send_recv(BOTH, TASK_FS, &msg); 37 | 38 | return msg.CNT; 39 | } 40 | -------------------------------------------------------------------------------- /mm/exec.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | #include "elf.h" 16 | 17 | 18 | /***************************************************************************** 19 | * do_exec 20 | *****************************************************************************/ 21 | /** 22 | * Perform the exec() system call. 23 | * 24 | * @return Zero if successful, otherwise -1. 25 | *****************************************************************************/ 26 | PUBLIC int do_exec() 27 | { 28 | /* get parameters from the message */ 29 | int name_len = mm_msg.NAME_LEN; /* length of filename */ 30 | int src = mm_msg.source; /* caller proc nr. */ 31 | assert(name_len < MAX_PATH); 32 | 33 | char pathname[MAX_PATH]; 34 | phys_copy((void*)va2la(TASK_MM, pathname), 35 | (void*)va2la(src, mm_msg.PATHNAME), 36 | name_len); 37 | pathname[name_len] = 0; /* terminate the string */ 38 | 39 | /* get the file size */ 40 | struct stat s; 41 | int ret = stat(pathname, &s); 42 | if (ret != 0) { 43 | printl("[INFO][MM] MM::do_exec()::stat() returns error. %s", pathname); 44 | return -1; 45 | } 46 | 47 | /* read the file */ 48 | int fd = open(pathname, O_RDWR); 49 | if (fd == -1) 50 | return -1; 51 | assert(s.st_size < MMBUF_SIZE); 52 | read(fd, mmbuf, s.st_size); 53 | close(fd); 54 | 55 | /* overwrite the current proc image with the new one */ 56 | Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*)(mmbuf); 57 | int i; 58 | for (i = 0; i < elf_hdr->e_phnum; i++) { 59 | Elf32_Phdr* prog_hdr = (Elf32_Phdr*)(mmbuf + elf_hdr->e_phoff + 60 | (i * elf_hdr->e_phentsize)); 61 | if (prog_hdr->p_type == PT_LOAD) { 62 | assert(prog_hdr->p_vaddr + prog_hdr->p_memsz < 63 | PROC_IMAGE_SIZE_DEFAULT); 64 | phys_copy((void*)va2la(src, (void*)prog_hdr->p_vaddr), 65 | (void*)va2la(TASK_MM, 66 | mmbuf + prog_hdr->p_offset), 67 | prog_hdr->p_filesz); 68 | } 69 | } 70 | 71 | /* setup the arg stack */ 72 | int orig_stack_len = mm_msg.BUF_LEN; 73 | char stackcopy[PROC_ORIGIN_STACK]; 74 | phys_copy((void*)va2la(TASK_MM, stackcopy), 75 | (void*)va2la(src, mm_msg.BUF), 76 | orig_stack_len); 77 | 78 | u8 * orig_stack = (u8*)(PROC_IMAGE_SIZE_DEFAULT - PROC_ORIGIN_STACK); 79 | 80 | int delta = (int)orig_stack - (int)mm_msg.BUF; 81 | 82 | int argc = 0; 83 | if (orig_stack_len) { /* has args */ 84 | char **q = (char**)stackcopy; 85 | for (; *q != 0; q++,argc++) 86 | *q += delta; 87 | } 88 | 89 | phys_copy((void*)va2la(src, orig_stack), 90 | (void*)va2la(TASK_MM, stackcopy), 91 | orig_stack_len); 92 | 93 | proc_table[src].regs.ecx = argc; /* argc */ 94 | proc_table[src].regs.eax = (u32)orig_stack; /* argv */ 95 | 96 | /* setup eip & esp */ 97 | proc_table[src].regs.eip = elf_hdr->e_entry; /* @see _start.asm */ 98 | proc_table[src].regs.esp = PROC_IMAGE_SIZE_DEFAULT - PROC_ORIGIN_STACK; 99 | 100 | strcpy(proc_table[src].name, pathname); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /mm/forkexit.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "stdio.h" 5 | #include "const.h" 6 | #include "protect.h" 7 | #include "string.h" 8 | #include "fs.h" 9 | #include "proc.h" 10 | #include "tty.h" 11 | #include "console.h" 12 | #include "global.h" 13 | #include "keyboard.h" 14 | #include "proto.h" 15 | 16 | 17 | PRIVATE void cleanup(struct proc * proc); 18 | 19 | /***************************************************************************** 20 | * do_fork 21 | *****************************************************************************/ 22 | /** 23 | * Perform the fork() syscall. 24 | * 25 | * @return Zero if success, otherwise -1. 26 | *****************************************************************************/ 27 | PUBLIC int do_fork() 28 | { 29 | /* find a free slot in proc_table */ 30 | struct proc* p = proc_table; 31 | int i; 32 | for (i = 0; i < NR_TASKS + NR_PROCS; i++,p++) 33 | if (p->p_flags == FREE_SLOT) 34 | break; 35 | 36 | int child_pid = i; 37 | assert(p == &proc_table[child_pid]); 38 | assert(child_pid >= NR_TASKS + NR_NATIVE_PROCS); 39 | if (i == NR_TASKS + NR_PROCS) /* no free slot */ 40 | return -1; 41 | assert(i < NR_TASKS + NR_PROCS); 42 | 43 | /* duplicate the process table */ 44 | int pid = mm_msg.source; 45 | u16 child_ldt_sel = p->ldt_sel; 46 | *p = proc_table[pid]; 47 | p->ldt_sel = child_ldt_sel; 48 | p->p_parent = pid; 49 | sprintf(p->name, "%s_%d", proc_table[pid].name, child_pid); 50 | 51 | /* duplicate the process: T, D & S */ 52 | struct descriptor * ppd; 53 | 54 | /* Text segment */ 55 | ppd = &proc_table[pid].ldts[INDEX_LDT_C]; 56 | /* base of T-seg, in bytes */ 57 | int caller_T_base = reassembly(ppd->base_high, 24, 58 | ppd->base_mid, 16, 59 | ppd->base_low); 60 | /* limit of T-seg, in 1 or 4096 bytes, 61 | depending on the G bit of descriptor */ 62 | int caller_T_limit = reassembly(0, 0, 63 | (ppd->limit_high_attr2 & 0xF), 16, 64 | ppd->limit_low); 65 | /* size of T-seg, in bytes */ 66 | int caller_T_size = ((caller_T_limit + 1) * 67 | ((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ? 68 | 4096 : 1)); 69 | 70 | /* Data & Stack segments */ 71 | ppd = &proc_table[pid].ldts[INDEX_LDT_RW]; 72 | /* base of D&S-seg, in bytes */ 73 | int caller_D_S_base = reassembly(ppd->base_high, 24, 74 | ppd->base_mid, 16, 75 | ppd->base_low); 76 | /* limit of D&S-seg, in 1 or 4096 bytes, 77 | depending on the G bit of descriptor */ 78 | int caller_D_S_limit = reassembly((ppd->limit_high_attr2 & 0xF), 16, 79 | 0, 0, 80 | ppd->limit_low); 81 | /* size of D&S-seg, in bytes */ 82 | int caller_D_S_size = ((caller_T_limit + 1) * 83 | ((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ? 84 | 4096 : 1)); 85 | 86 | /* we don't separate T, D & S segments, so we have: */ 87 | assert((caller_T_base == caller_D_S_base ) && 88 | (caller_T_limit == caller_D_S_limit) && 89 | (caller_T_size == caller_D_S_size )); 90 | 91 | /* base of child proc, T, D & S segments share the same space, 92 | so we allocate memory just once */ 93 | int child_base = alloc_mem(child_pid, caller_T_size); 94 | 95 | /* child is a copy of the parent */ 96 | phys_copy((void*)child_base, (void*)caller_T_base, caller_T_size); 97 | 98 | /* child's LDT */ 99 | init_desc(&p->ldts[INDEX_LDT_C], 100 | child_base, 101 | (PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT, 102 | DA_LIMIT_4K | DA_32 | DA_C | PRIVILEGE_USER << 5); 103 | init_desc(&p->ldts[INDEX_LDT_RW], 104 | child_base, 105 | (PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT, 106 | DA_LIMIT_4K | DA_32 | DA_DRW | PRIVILEGE_USER << 5); 107 | 108 | /* tell FS, see fs_fork() */ 109 | MESSAGE msg2fs; 110 | msg2fs.type = FORK; 111 | msg2fs.PID = child_pid; 112 | send_recv(BOTH, TASK_FS, &msg2fs); 113 | 114 | /* child PID will be returned to the parent proc */ 115 | mm_msg.PID = child_pid; 116 | 117 | /* birth of the child */ 118 | MESSAGE m; 119 | m.type = SYSCALL_RET; 120 | m.RETVAL = 0; 121 | m.PID = 0; 122 | send_recv(SEND, child_pid, &m); 123 | 124 | return 0; 125 | } 126 | 127 | /***************************************************************************** 128 | * do_exit 129 | *****************************************************************************/ 130 | /** 131 | * Perform the exit() syscall. 132 | * 133 | * If proc A calls exit(), then MM will do the following in this routine: 134 | * <1> inform FS so that the fd-related things will be cleaned up 135 | * <2> free A's memory 136 | * <3> set A.exit_status, which is for the parent 137 | * <4> depends on parent's status. if parent (say P) is: 138 | * (1) WAITING 139 | * - clean P's WAITING bit, and 140 | * - send P a message to unblock it 141 | * - release A's proc_table[] slot 142 | * (2) not WAITING 143 | * - set A's HANGING bit 144 | * <5> iterate proc_table[], if proc B is found as A's child, then: 145 | * (1) make INIT the new parent of B, and 146 | * (2) if INIT is WAITING and B is HANGING, then: 147 | * - clean INIT's WAITING bit, and 148 | * - send INIT a message to unblock it 149 | * - release B's proc_table[] slot 150 | * else 151 | * if INIT is WAITING but B is not HANGING, then 152 | * - B will call exit() 153 | * if B is HANGING but INIT is not WAITING, then 154 | * - INIT will call wait() 155 | * 156 | * TERMs: 157 | * - HANGING: everything except the proc_table entry has been cleaned up. 158 | * - WAITING: a proc has at least one child, and it is waiting for the 159 | * child(ren) to exit() 160 | * - zombie: say P has a child A, A will become a zombie if 161 | * - A exit(), and 162 | * - P does not wait(), neither does it exit(). that is to say, P just 163 | * keeps running without terminating itself or its child 164 | * 165 | * @param status Exiting status for parent. 166 | * 167 | *****************************************************************************/ 168 | PUBLIC void do_exit(int status) 169 | { 170 | int i; 171 | int pid = mm_msg.source; /* PID of caller */ 172 | int parent_pid = proc_table[pid].p_parent; 173 | struct proc * p = &proc_table[pid]; 174 | 175 | /* tell FS, see fs_exit() */ 176 | MESSAGE msg2fs; 177 | msg2fs.type = EXIT; 178 | msg2fs.PID = pid; 179 | send_recv(BOTH, TASK_FS, &msg2fs); 180 | 181 | free_mem(pid); 182 | 183 | p->exit_status = status; 184 | 185 | if (proc_table[parent_pid].p_flags & WAITING) { /* parent is waiting */ 186 | proc_table[parent_pid].p_flags &= ~WAITING; 187 | cleanup(&proc_table[pid]); 188 | } 189 | else { /* parent is not waiting */ 190 | proc_table[pid].p_flags |= HANGING; 191 | } 192 | 193 | /* if the proc has any child, make INIT the new parent */ 194 | for (i = 0; i < NR_TASKS + NR_PROCS; i++) { 195 | if (proc_table[i].p_parent == pid) { /* is a child */ 196 | proc_table[i].p_parent = INIT; 197 | if ((proc_table[INIT].p_flags & WAITING) && 198 | (proc_table[i].p_flags & HANGING)) { 199 | proc_table[INIT].p_flags &= ~WAITING; 200 | cleanup(&proc_table[i]); 201 | } 202 | } 203 | } 204 | } 205 | 206 | /***************************************************************************** 207 | * cleanup 208 | *****************************************************************************/ 209 | /** 210 | * Do the last jobs to clean up a proc thoroughly: 211 | * - Send proc's parent a message to unblock it, and 212 | * - release proc's proc_table[] entry 213 | * 214 | * @param proc Process to clean up. 215 | *****************************************************************************/ 216 | PRIVATE void cleanup(struct proc * proc) 217 | { 218 | MESSAGE msg2parent; 219 | msg2parent.type = SYSCALL_RET; 220 | msg2parent.PID = proc2pid(proc); 221 | msg2parent.STATUS = proc->exit_status; 222 | send_recv(SEND, proc->p_parent, &msg2parent); 223 | 224 | proc->p_flags = FREE_SLOT; 225 | } 226 | 227 | /***************************************************************************** 228 | * do_wait 229 | *****************************************************************************/ 230 | /** 231 | * Perform the wait() syscall. 232 | * 233 | * If proc P calls wait(), then MM will do the following in this routine: 234 | * <1> iterate proc_table[], 235 | * if proc A is found as P's child and it is HANGING 236 | * - reply to P (cleanup() will send P a messageto unblock it) 237 | * - release A's proc_table[] entry 238 | * - return (MM will go on with the next message loop) 239 | * <2> if no child of P is HANGING 240 | * - set P's WAITING bit 241 | * <3> if P has no child at all 242 | * - reply to P with error 243 | * <4> return (MM will go on with the next message loop) 244 | * 245 | *****************************************************************************/ 246 | PUBLIC void do_wait() 247 | { 248 | int pid = mm_msg.source; 249 | 250 | int i; 251 | int children = 0; 252 | struct proc* p_proc = proc_table; 253 | for (i = 0; i < NR_TASKS + NR_PROCS; i++,p_proc++) { 254 | if (p_proc->p_parent == pid) { 255 | children++; 256 | if (p_proc->p_flags & HANGING) { 257 | cleanup(p_proc); 258 | return; 259 | } 260 | } 261 | } 262 | 263 | if (children) { 264 | /* has children, but no child is HANGING */ 265 | proc_table[pid].p_flags |= WAITING; 266 | } 267 | else { 268 | /* no child at all */ 269 | MESSAGE msg; 270 | msg.type = SYSCALL_RET; 271 | msg.PID = NO_TASK; 272 | send_recv(SEND, pid, &msg); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /mm/main.c: -------------------------------------------------------------------------------- 1 | /*Hanbings 3219065882@qq.com*/ 2 | 3 | #include "type.h" 4 | #include "config.h" 5 | #include "stdio.h" 6 | #include "const.h" 7 | #include "protect.h" 8 | #include "string.h" 9 | #include "fs.h" 10 | #include "proc.h" 11 | #include "tty.h" 12 | #include "console.h" 13 | #include "global.h" 14 | #include "keyboard.h" 15 | #include "proto.h" 16 | 17 | PUBLIC void do_fork_test(); 18 | 19 | PRIVATE void init_mm(); 20 | 21 | /***************************************************************************** 22 | * task_mm 23 | *****************************************************************************/ 24 | /** 25 | * The main loop of TASK MM. 26 | * 27 | *****************************************************************************/ 28 | PUBLIC void task_mm() 29 | { 30 | init_mm(); 31 | 32 | while (1) { 33 | send_recv(RECEIVE, ANY, &mm_msg); 34 | int src = mm_msg.source; 35 | int reply = 1; 36 | 37 | int msgtype = mm_msg.type; 38 | 39 | switch (msgtype) { 40 | case FORK: 41 | mm_msg.RETVAL = do_fork(); 42 | break; 43 | case EXIT: 44 | do_exit(mm_msg.STATUS); 45 | reply = 0; 46 | break; 47 | case EXEC: 48 | mm_msg.RETVAL = do_exec(); 49 | break; 50 | case WAIT: 51 | do_wait(); 52 | reply = 0; 53 | break; 54 | default: 55 | dump_msg("[INFO][MM] MM::unknown msg", &mm_msg); 56 | assert(0); 57 | break; 58 | } 59 | 60 | if (reply) { 61 | mm_msg.type = SYSCALL_RET; 62 | send_recv(SEND, src, &mm_msg); 63 | } 64 | } 65 | } 66 | 67 | /***************************************************************************** 68 | * init_mm 69 | *****************************************************************************/ 70 | /** 71 | * Do some initialization work. 72 | * 73 | *****************************************************************************/ 74 | PRIVATE void init_mm() 75 | { 76 | struct boot_params bp; 77 | get_boot_params(&bp); 78 | 79 | memory_size = bp.mem_size; 80 | 81 | /* print memory size */ 82 | printl("[INFO][MM] memsize:%dMB\n", memory_size / (1024 * 1024)); 83 | } 84 | 85 | /***************************************************************************** 86 | * alloc_mem 87 | *****************************************************************************/ 88 | /** 89 | * Allocate a memory block for a proc. 90 | * 91 | * @param pid Which proc the memory is for. 92 | * @param memsize How many bytes is needed. 93 | * 94 | * @return The base of the memory just allocated. 95 | *****************************************************************************/ 96 | PUBLIC int alloc_mem(int pid, int memsize) 97 | { 98 | assert(pid >= (NR_TASKS + NR_NATIVE_PROCS)); 99 | if (memsize > PROC_IMAGE_SIZE_DEFAULT) { 100 | panic("[ERRO][MM] unsupported memory request: %d. " 101 | "(should be less than %d)", 102 | memsize, 103 | PROC_IMAGE_SIZE_DEFAULT); 104 | } 105 | 106 | int base = PROCS_BASE + 107 | (pid - (NR_TASKS + NR_NATIVE_PROCS)) * PROC_IMAGE_SIZE_DEFAULT; 108 | 109 | if (base + memsize >= memory_size) 110 | panic("[ERRO][MM]memory allocation failed. pid:%d", pid); 111 | 112 | return base; 113 | } 114 | 115 | /***************************************************************************** 116 | * free_mem 117 | *****************************************************************************/ 118 | /** 119 | * Free a memory block. Because a memory block is corresponding with a PID, so 120 | * we don't need to really `free' anything. In another word, a memory block is 121 | * dedicated to one and only one PID, no matter what proc actually uses this 122 | * PID. 123 | * 124 | * @param pid Whose memory is to be freed. 125 | * 126 | * @return Zero if success. 127 | *****************************************************************************/ 128 | PUBLIC int free_mem(int pid) 129 | { 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /scripts/genlog: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################################################# 4 | # Usage: 5 | # ./genlog 6 | # Note: 7 | # extract syslog from disk 8 | # 9 | # BUGS: 10 | # Forrest Y. Yu 11 | # Nov. 21, 2008 12 | ################################################################################################################# 13 | 14 | echo 15 | echo "[syslog]" 16 | echo "--------" 17 | syslog_tmp_file=/tmp/prntdisk.tmp 18 | syslog_file=./llsyslog 19 | dd if=80m.img of=$syslog_tmp_file bs=1 count=32 skip=`echo "obase=10;ibase=16;1C88000" | bc` 2> /dev/null 20 | dd if=80m.img of=$syslog_file bs=1 count=`head -n 1 $syslog_tmp_file | sed 's/\ //g'` skip=`echo "obase=10;ibase=16;1C88000" | bc` 2> /dev/null 21 | echo >> $syslog_file 22 | echo "time: "`cat $syslog_file | head -n 3 | tail -n 1` 23 | echo 24 | cat $syslog_file | sed '1,3d' > filedesc.dot 25 | cat filedesc.dot | scripts/splitgraphs 26 | gthumb . & 27 | echo 28 | 29 | exit 0 30 | 31 | -------------------------------------------------------------------------------- /scripts/splitgraphs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while read line 4 | do 5 | kw=`echo $line | awk -F "[ ]" '{print $1}'` 6 | if [ "$kw" == "digraph" ]; then 7 | gname=`echo $line | awk -F "[ ]" '{print $2}'` 8 | fname=$gname".dot" 9 | pname=$gname".png" 10 | echo $kw" "$gname 11 | 12 | echo $line > $fname 13 | while read line 14 | do 15 | if [ "$line" == "--separator--" ]; then 16 | dot -Tpng $fname -o $pname 17 | break 18 | fi 19 | 20 | echo $line >> $fname 21 | done 22 | fi 23 | done 24 | 25 | --------------------------------------------------------------------------------