(basic, not much tested) keyboard, better panic
This commit is contained in:
		
							parent
							
								
									b8284137d4
								
							
						
					
					
						commit
						1e4a254674
					
				
					 32 changed files with 726 additions and 175 deletions
				
			
		|  | @ -9,14 +9,16 @@ syscall is int 0x30 | ||||||
| system call number in eax | system call number in eax | ||||||
| args in ebx, ecx, edx, esi, edi | args in ebx, ecx, edx, esi, edi | ||||||
| result in eax | result in eax | ||||||
|   note: do not assume eax is unmodified if there is no value to be returned |  | ||||||
| modifies ecx, edx | modifies ecx, edx | ||||||
|  | modifies eax even if no value is returned | ||||||
| see table 1 | see table 1 | ||||||
| 
 | 
 | ||||||
| file system calls have units of bytes unless otherwise specified | file system calls have units of bytes unless otherwise specified | ||||||
| functions returning handles or pointers use 0 to indicate error | functions returning handles or pointers use 0 to indicate error | ||||||
| functions returning "success" use 1 for success and 0 for failure | functions returning "success" use 1 for success and 0 for failure | ||||||
| see keys.txt for the return type of the "get key" system call | see keys.txt for the return type of the "get key" system call | ||||||
|  | the edx register of "start task" is a pointer to a null-terminated string. | ||||||
|  |   a pointer to a readonly copy of this string is put into the new task's edx. | ||||||
| 
 | 
 | ||||||
| invalid system call numbers change eax to -1, and have no other effect. | invalid system call numbers change eax to -1, and have no other effect. | ||||||
| 
 | 
 | ||||||
|  | @ -24,12 +26,12 @@ invalid system call numbers change eax to -1, and have no other effect. | ||||||
| table 1: | table 1: | ||||||
| 
 | 
 | ||||||
|  function      | eax | eax out       | ebx           | ecx         | edx       | esi    | edi |  function      | eax | eax out       | ebx           | ecx         | edx       | esi    | edi | ||||||
| ---------------|-----|---------------|---------------|-------------|-------|--------|----- | ---------------|-----|---------------|---------------|-------------|-----------|--------|----- | ||||||
|  open file     | 0x0 | handle        | drive number  | path        |           |        | |  open file     | 0x0 | handle        | drive number  | path        |           |        | | ||||||
|  close file    | 0x1 |               | handle        |             |           |        | |  close file    | 0x1 |               | handle        |             |           |        | | ||||||
|  file read     | 0x2 | read          | handle        | file offset | count     | buffer | |  file read     | 0x2 | read          | handle        | file offset | count     | buffer | | ||||||
|  get file size | 0x3 | size          | handle        |             |           |        | |  get file size | 0x3 | size          | handle        |             |           |        | | ||||||
|  start task    | 0x4 | success       | drive number  | path        |       |        | |  start task    | 0x4 | success       | drive number  | path        | passed sz |        | | ||||||
|  log string    | 0x5 |               | sz string     |             |           |        | |  log string    | 0x5 |               | sz string     |             |           |        | | ||||||
|  get key       | 0x6 | keycode       |               |             |           |        | |  get key       | 0x6 | keycode       |               |             |           |        | | ||||||
|  allocate ram  | 0x7 | start pointer | pages         |             |           |        | |  allocate ram  | 0x7 | start pointer | pages         |             |           |        | | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								doc/keys.txt
									
										
									
									
									
								
							
							
						
						
									
										73
									
								
								doc/keys.txt
									
										
									
									
									
								
							|  | @ -2,7 +2,7 @@ keycodes are 32-bit integers. | ||||||
| 
 | 
 | ||||||
| the low byte indicates the key itself. for printable characters (and keys with | the low byte indicates the key itself. for printable characters (and keys with | ||||||
| reasonable translations to ascii control codes), this is the ascii code. for | reasonable translations to ascii control codes), this is the ascii code. for | ||||||
| other ones, something in the range of 0x80 to 0xff is used, seen in table 1. | other ones, something in the range of 0x80 to 0xef is used, seen in table 1. | ||||||
| 
 | 
 | ||||||
| the top 24 bits indicate several flags. these are seen in table 2, where bit 0 | the top 24 bits indicate several flags. these are seen in table 2, where bit 0 | ||||||
| is the lowest bit of the second lowest byte of the keycode, and bit 23 is the | is the lowest bit of the second lowest byte of the keycode, and bit 23 is the | ||||||
|  | @ -18,10 +18,73 @@ user.c of the "knob" library for an example of this. | ||||||
| table 1: | table 1: | ||||||
| 
 | 
 | ||||||
|  code | key |  code | key | ||||||
| ------|----- | ------|--------------- | ||||||
|  0x80 | |  0x80 | caps lock | ||||||
|  .... | |  0x81 | insert | ||||||
|  0xff | |  0x82 | num lock | ||||||
|  |  0x83 | scroll lock | ||||||
|  |  0x84 | left shift | ||||||
|  |  0x85 | right shift | ||||||
|  |  0x86 | left alt | ||||||
|  |  0x87 | right alt | ||||||
|  |  0x88 | left control | ||||||
|  |  0x89 | right control | ||||||
|  |  0x8a | left meta | ||||||
|  |  0x8b | right meta | ||||||
|  |  0x8c | reserved | ||||||
|  |  .... | reserved | ||||||
|  |  0x97 | reserved | ||||||
|  |  0x98 | unassigned | ||||||
|  |  .... | unassigned | ||||||
|  |  0x9f | unassigned | ||||||
|  |  0xa0 | F1 | ||||||
|  |  0xa1 | F2 | ||||||
|  |  0xa2 | F3 | ||||||
|  |  0xa3 | F4 | ||||||
|  |  0xa4 | F5 | ||||||
|  |  0xa5 | F6 | ||||||
|  |  0xa6 | F7 | ||||||
|  |  0xa7 | F8 | ||||||
|  |  0xa8 | F9 | ||||||
|  |  0xa9 | F10 | ||||||
|  |  0xaa | F11 | ||||||
|  |  0xab | F12 | ||||||
|  |  0xac | unassigned | ||||||
|  |  .... | unassigned | ||||||
|  |  0xaf | unassigned | ||||||
|  |  0xb0 | numpad 0 | ||||||
|  |  0xb1 | numpad 1 | ||||||
|  |  0xb2 | numpad 2 | ||||||
|  |  0xb3 | numpad 3 | ||||||
|  |  0xb4 | numpad 4 | ||||||
|  |  0xb5 | numpad 5 | ||||||
|  |  0xb6 | numpad 6 | ||||||
|  |  0xb7 | numpad 7 | ||||||
|  |  0xb8 | numpad 8 | ||||||
|  |  0xb9 | numpad 9 | ||||||
|  |  0xba | numpad * | ||||||
|  |  0xbb | numpad + | ||||||
|  |  0xbc | numpad Enter | ||||||
|  |  0xbd | numpad - | ||||||
|  |  0xbe | numpad . | ||||||
|  |  0xbf | numpad / | ||||||
|  |  0xc0 | unassigned | ||||||
|  |  0xc1 | delete | ||||||
|  |  0xc2 | home | ||||||
|  |  0xc3 | end | ||||||
|  |  0xc4 | page up | ||||||
|  |  0xc5 | page down | ||||||
|  |  0xc6 | up | ||||||
|  |  0xc7 | down | ||||||
|  |  0xc8 | left | ||||||
|  |  0xc9 | right | ||||||
|  |  0xca | escape | ||||||
|  |  0xcb | menu | ||||||
|  |  0xcc | pause | ||||||
|  |  0xcd | print screen | ||||||
|  |  0xce | unassigned | ||||||
|  |  .... | unassigned | ||||||
|  |  0xef | unassigned | ||||||
| 
 | 
 | ||||||
| table 2: | table 2: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,2 @@ | ||||||
| BIN/MEMINFO.ELF | BIN/MEMINFO.ELF | ||||||
| BIN/HELLO.ELF | BIN/HIGHWAY.ELF | ||||||
							
								
								
									
										25
									
								
								makefile
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								makefile
									
										
									
									
									
								
							|  | @ -1,12 +1,14 @@ | ||||||
| kgccargs = -Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=malloc -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables | kgccargs = -Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables | ||||||
| ugccargs = ${kgccargs} -Isrc/user/include | ugccargs = ${kgccargs} -Isrc/user/include | ||||||
| nasmargs = -f elf32 | nasmargs = -f elf32 | ||||||
| partlink = -r -m elf_i386 | partlink = -r -m elf_i386 | ||||||
| 
 | 
 | ||||||
| out/disk.vdi: out/disk.img | out/disk.vdi: out/disk.img | ||||||
|  | 	rm out/disk.vdi || true | ||||||
| 	VBoxManage convertfromraw out/disk.img out/disk.vdi --uuid a61929ed-3bf2-45ff-b98a-44f87c616dba | 	VBoxManage convertfromraw out/disk.img out/disk.vdi --uuid a61929ed-3bf2-45ff-b98a-44f87c616dba | ||||||
| 
 | 
 | ||||||
| out/disk.img: out/kernel.bin out/boot.bin out/fs | out/disk.img: out/kernel.bin out/boot.bin out/fs | ||||||
|  |   #TODO: have this regenerate after out/fs | ||||||
| 	mkdir -p obj | 	mkdir -p obj | ||||||
| 	/sbin/mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 65 -s 1 -S 512 obj/shadow.img 8192 | 	/sbin/mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 65 -s 1 -S 512 obj/shadow.img 8192 | ||||||
| 	echo -n -e '\xeb\x3c' > obj/jmp.bin | 	echo -n -e '\xeb\x3c' > obj/jmp.bin | ||||||
|  | @ -22,12 +24,13 @@ debug: out/disk.img | ||||||
| clean: | clean: | ||||||
| 	rm -r obj out || true | 	rm -r obj out || true | ||||||
| 
 | 
 | ||||||
| out/fs: obj/hello.elf obj/init.elf obj/meminfo.elf | out/fs/bin/%.elf: obj/%.elf | ||||||
| 	mkdir -p out/fs/bin  | 	mkdir -p $(shell dirname $@) | ||||||
|  | 	objcopy -S $< $@ | ||||||
|  | 
 | ||||||
|  | out/fs: out/fs/bin/init.elf out/fs/bin/meminfo.elf out/fs/bin/highway.elf | ||||||
|  | 	mkdir -p out/fs | ||||||
| 	cp -r fs-skel/* out/fs/ | 	cp -r fs-skel/* out/fs/ | ||||||
| 	objcopy -S obj/hello.elf    out/fs/bin/hello.elf |  | ||||||
| 	objcopy -S obj/init.elf     out/fs/bin/init.elf |  | ||||||
| 	objcopy -S obj/meminfo.elf  out/fs/bin/meminfo.elf |  | ||||||
| 
 | 
 | ||||||
| obj/kernel/%.ko: src/kernel/%.c | obj/kernel/%.ko: src/kernel/%.c | ||||||
| 	mkdir -p $(shell dirname $@) | 	mkdir -p $(shell dirname $@) | ||||||
|  | @ -42,7 +45,7 @@ out/kernel.bin: obj/kernel/drive.ko  obj/kernel/fat.ko   obj/kernel/ide.ko    \ | ||||||
|                 obj/kernel/main2.ko  obj/kernel/pmap.ko  obj/kernel/paging.ko \
 |                 obj/kernel/main2.ko  obj/kernel/pmap.ko  obj/kernel/paging.ko \
 | ||||||
|                 obj/kernel/panic.ko  obj/kernel/pci.ko   obj/kernel/elf.ko    \
 |                 obj/kernel/panic.ko  obj/kernel/pci.ko   obj/kernel/elf.ko    \
 | ||||||
|                 obj/kernel/serial.ko obj/kernel/task.ko  obj/kernel/util.ko   \
 |                 obj/kernel/serial.ko obj/kernel/task.ko  obj/kernel/util.ko   \
 | ||||||
|                 obj/kernel/vga.ko    obj/kernel/isrs.kao |                 obj/kernel/vga.ko    obj/kernel/isrs.kao obj/kernel/kbd.ko | ||||||
| 	mkdir -p out | 	mkdir -p out | ||||||
| 	ld -T src/kernel/elf-link.ld obj/kernel/* -o obj/kernel.elf | 	ld -T src/kernel/elf-link.ld obj/kernel/* -o obj/kernel.elf | ||||||
| 	objcopy -O binary obj/kernel.elf out/kernel.bin | 	objcopy -O binary obj/kernel.elf out/kernel.bin | ||||||
|  | @ -61,14 +64,14 @@ obj/%.ao: src/user/%.asm | ||||||
| 
 | 
 | ||||||
| obj/knob.so: obj/knob/env.o  obj/knob/file.o   obj/knob/format.o \ | obj/knob.so: obj/knob/env.o  obj/knob/file.o   obj/knob/format.o \ | ||||||
|              obj/knob/heap.o obj/knob/quit.o   obj/knob/user.o   \
 |              obj/knob/heap.o obj/knob/quit.o   obj/knob/user.o   \
 | ||||||
|              obj/knob/task.o obj/knob/entry.ao |              obj/knob/task.o obj/knob/entry.ao obj/knob/block.o | ||||||
| 	ld ${partlink} obj/knob/* -o obj/knob.so | 	ld ${partlink} obj/knob/* -o obj/knob.so | ||||||
| 
 | 
 | ||||||
| obj/hello.elf: obj/hello/hello.o obj/knob.so |  | ||||||
| 	ld -T src/user/elf.ld obj/hello/* obj/knob.so -o obj/hello.elf |  | ||||||
| 
 |  | ||||||
| obj/init.elf: obj/init/init.o obj/knob.so | obj/init.elf: obj/init/init.o obj/knob.so | ||||||
| 	ld -T src/user/elf.ld obj/init/* obj/knob.so -o obj/init.elf | 	ld -T src/user/elf.ld obj/init/* obj/knob.so -o obj/init.elf | ||||||
| 
 | 
 | ||||||
| obj/meminfo.elf: obj/meminfo/meminfo.o obj/knob.so | obj/meminfo.elf: obj/meminfo/meminfo.o obj/knob.so | ||||||
| 	ld -T src/user/elf.ld obj/meminfo/* obj/knob.so -o obj/meminfo.elf | 	ld -T src/user/elf.ld obj/meminfo/* obj/knob.so -o obj/meminfo.elf | ||||||
|  | 
 | ||||||
|  | obj/highway.elf: obj/highway/highway.o obj/knob.so | ||||||
|  | 	ld -T src/user/elf.ld obj/highway/* obj/knob.so -o obj/highway.elf | ||||||
|  | @ -4,5 +4,4 @@ set disassembly-flavor intel | ||||||
| layout reg | layout reg | ||||||
| break main | break main | ||||||
| break panic | break panic | ||||||
| break _before_start_task |  | ||||||
| cont | cont | ||||||
|  |  | ||||||
|  | @ -15,15 +15,15 @@ static file_id_t unknown_get_file(const struct drive *d, const char *path) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void unknown_free_file(const struct drive *d, file_id_t fid) { | static void unknown_free_file(const struct drive *d, file_id_t fid) { | ||||||
|   panic("Free file called on unknown file system"); |   PANIC("Free file called on unknown file system."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void unknown_load_sector(const struct drive *d, file_id_t fid, uint32_t sector, void *at) { | static void unknown_load_sector(const struct drive *d, file_id_t fid, uint32_t sector, void *at) { | ||||||
|   panic("Load sector called on unknown file system"); |   PANIC("Load sector called on unknown file system."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t unknown_get_file_length(const struct drive *d, file_id_t fid) { | static uint32_t unknown_get_file_length(const struct drive *d, file_id_t fid) { | ||||||
|   panic("Get file length called on unknown file system"); |   PANIC("Get file length called on unknown file system."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __attribute__ ((const)) | __attribute__ ((const)) | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ struct ph_entry { | ||||||
|   uint32_t align; |   uint32_t align; | ||||||
| } __attribute__ ((packed)); | } __attribute__ ((packed)); | ||||||
| 
 | 
 | ||||||
| bool try_elf_run(const struct drive *d, const char *path) { | bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma) { | ||||||
|   file_id_t h = d->get_file(d, path); |   file_id_t h = d->get_file(d, path); | ||||||
|   if (!h) |   if (!h) | ||||||
|     return false; |     return false; | ||||||
|  | @ -109,9 +109,23 @@ bool try_elf_run(const struct drive *d, const char *path) { | ||||||
|   free_pages(phtable, phtable_pages); |   free_pages(phtable, phtable_pages); | ||||||
|   d->free_file(d, h); |   d->free_file(d, h); | ||||||
| 
 | 
 | ||||||
|  |   const char *pass = vma_to_pma(active_task->page_directory, pass_old_vma); | ||||||
|  | 
 | ||||||
|  |   uint32_t pass_l = 0; | ||||||
|  |   while (pass[pass_l++]) | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   void *pass_vma; | ||||||
|  |   void *pass_pma; | ||||||
|  |   user_allocate_anywhere_readonly_together(pd, ((pass_l - 1) >> 12) + 1, &pass_vma, &pass_pma); | ||||||
|  |   //TODO: handle error condition
 | ||||||
|  | 
 | ||||||
|  |   memcpy(pass_pma, pass, pass_l); | ||||||
|  | 
 | ||||||
|   struct task_state tstate; |   struct task_state tstate; | ||||||
|   tstate.page_directory = pd; |   tstate.page_directory = pd; | ||||||
|   tstate.ret_addr = ehead.entry_vma; |   tstate.ret_addr = ehead.entry_vma; | ||||||
|  |   tstate.edx = (uint32_t)pass_vma; | ||||||
|   new_task(tstate); |   new_task(tstate); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  | @ -4,6 +4,6 @@ | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "drive.h" | #include "drive.h" | ||||||
| 
 | 
 | ||||||
| bool try_elf_run(const struct drive *d, const char *path); | bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -89,7 +89,7 @@ static struct fat_info *next_fi; | ||||||
| static void alloc_next_fi() { | static void alloc_next_fi() { | ||||||
|   if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff)) |   if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff)) | ||||||
|     if (!(next_fi = allocate_kernel_pages(1))) |     if (!(next_fi = allocate_kernel_pages(1))) | ||||||
|       panic("Out of memory in FAT driver."); |       PANIC("Out of memory in FAT driver."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct drive *cur_drive; | static const struct drive *cur_drive; | ||||||
|  | @ -183,9 +183,9 @@ static const char *split_path(const char *path, uint8_t *fat_name_buffer) { | ||||||
|         ++pi; |         ++pi; | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|         panic("Bad path in FAT16 driver"); |         PANIC("Bad path in FAT16 driver."); | ||||||
|     else if (((fi == 8) && (path[pi - 1] != EXT_SEP_CHAR)) || (fi == 11)) |     else if (((fi == 8) && (path[pi - 1] != EXT_SEP_CHAR)) || (fi == 11)) | ||||||
|       panic("Bad path in FAT16 driver"); |       PANIC("Bad path in FAT16 driver."); | ||||||
|     else { |     else { | ||||||
|       fat_name_buffer[fi++] = (uint8_t)path[pi++]; |       fat_name_buffer[fi++] = (uint8_t)path[pi++]; | ||||||
|     } |     } | ||||||
|  | @ -229,7 +229,7 @@ static file_id_t fat_get_file(const struct drive *d, const char *path) { | ||||||
|       return n; |       return n; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   panic("Maximum number of files open reached for FAT drive."); |   PANIC("Maximum number of files open reached for FAT drive."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void fat_free_file(const struct drive *d, file_id_t fid) { | static void fat_free_file(const struct drive *d, file_id_t fid) { | ||||||
|  | @ -365,7 +365,7 @@ void init_fat() { | ||||||
| 
 | 
 | ||||||
| bool try_fat_init_drive(struct drive *d) { | bool try_fat_init_drive(struct drive *d) { | ||||||
|   if (next_id >= MAX_FAT_DRIVES) |   if (next_id >= MAX_FAT_DRIVES) | ||||||
|     panic("Maximum number of FAT drives reached."); |     PANIC("Maximum number of FAT drives reached."); | ||||||
| 
 | 
 | ||||||
|   if (!d->read_sectors(d, 0, 1, fat_driver_buffer)) |   if (!d->read_sectors(d, 0, 1, fat_driver_buffer)) | ||||||
|     return false; |     return false; | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ static uint8_t wait_for_ready(uint16_t base_port) { | ||||||
|   for (spinner_t n = -1; n; --n) { |   for (spinner_t n = -1; n; --n) { | ||||||
|     uint8_t s = inb(base_port | ATA_REG_STATUS); |     uint8_t s = inb(base_port | ATA_REG_STATUS); | ||||||
|     if (s & ATA_STATUS_ERROR) |     if (s & ATA_STATUS_ERROR) | ||||||
|       panic("Error status in IDE driver."); |       PANIC("Error status in IDE driver."); | ||||||
|     if (s & ATA_STATUS_DRIVE_READY) |     if (s & ATA_STATUS_DRIVE_READY) | ||||||
|       return s; |       return s; | ||||||
|   } |   } | ||||||
|   panic("Spun out in IDE driver."); |   PANIC("Spun out in IDE driver."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //returns the status after waiting
 | //returns the status after waiting
 | ||||||
|  | @ -38,7 +38,7 @@ static uint8_t wait_for_error_or_ready(uint16_t base_port) { | ||||||
|     if (s & (ATA_STATUS_DRIVE_READY | ATA_STATUS_ERROR)) |     if (s & (ATA_STATUS_DRIVE_READY | ATA_STATUS_ERROR)) | ||||||
|       return s; |       return s; | ||||||
|   } |   } | ||||||
|   panic("Spun out in IDE driver."); |   PANIC("Spun out in IDE driver."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //returns the status after waiting
 | //returns the status after waiting
 | ||||||
|  | @ -48,9 +48,9 @@ static uint8_t wait_for_data_ready_not_busy(uint16_t base_port) { | ||||||
|     if (!(s & ATA_STATUS_BUSY) && (s & ATA_STATUS_DATA_READY)) |     if (!(s & ATA_STATUS_BUSY) && (s & ATA_STATUS_DATA_READY)) | ||||||
|       return s; |       return s; | ||||||
|     if (s & ATA_STATUS_ERROR) |     if (s & ATA_STATUS_ERROR) | ||||||
|       panic("Error status in IDE driver."); |       PANIC("Error status in IDE driver."); | ||||||
|   } |   } | ||||||
|   panic("Spun out in IDE driver."); |   PANIC("Spun out in IDE driver."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { | static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { | ||||||
|  | @ -62,9 +62,9 @@ static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count | ||||||
|     return 0; |     return 0; | ||||||
| 
 | 
 | ||||||
|   if (start & 0xf0000000) |   if (start & 0xf0000000) | ||||||
|     panic("IDE ATA driver does not support reads starting past 256MiB currently."); |     PANIC("IDE ATA driver does not support reads starting past 256MiB currently."); | ||||||
|   if (count & 0xffffff00) |   if (count & 0xffffff00) | ||||||
|     panic("IDE ATA driver does not support reads over 128kiB in length currently."); |     PANIC("IDE ATA driver does not support reads over 128kiB in length currently."); | ||||||
| 
 | 
 | ||||||
|   uint32_t lba = start & 0x00ffffff; |   uint32_t lba = start & 0x00ffffff; | ||||||
| 
 | 
 | ||||||
|  | @ -92,7 +92,7 @@ static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { | static uint32_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { | ||||||
|   panic("IDE ATA writing not implemented yet"); |   PANIC("IDE ATA writing not implemented yet."); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -104,11 +104,11 @@ static uint32_t ide_atapi_rs(const struct drive *d, uint32_t start, uint32_t cou | ||||||
|   if (!count) |   if (!count) | ||||||
|     return 0; |     return 0; | ||||||
| 
 | 
 | ||||||
|    |   PANIC("IDE ATAPI reading not implemented yet."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { | static uint32_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { | ||||||
|   panic("IDE ATAPI writing not implemented yet"); |   PANIC("IDE ATAPI writing not implemented yet."); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -122,7 +122,7 @@ struct id_space { | ||||||
| 
 | 
 | ||||||
| static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { | static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { | ||||||
|   if (n_ide_drives == MAX_IDE_DRIVES) |   if (n_ide_drives == MAX_IDE_DRIVES) | ||||||
|     panic("Maximum number of IDE drives reached."); |     PANIC("Maximum number of IDE drives reached."); | ||||||
| 
 | 
 | ||||||
|   struct ide_drive_info *next = ide_drives + n_ide_drives; |   struct ide_drive_info *next = ide_drives + n_ide_drives; | ||||||
|   struct drive next_d; |   struct drive next_d; | ||||||
|  | @ -161,7 +161,7 @@ static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { | ||||||
|   else { |   else { | ||||||
|     uint16_t code = inb(base_port | 0x4) + (inb(base_port | 0x5) << 8); |     uint16_t code = inb(base_port | 0x4) + (inb(base_port | 0x5) << 8); | ||||||
|     if (!code) { |     if (!code) { | ||||||
|       panic("PATA identification aborted."); |       PANIC("PATA identification aborted."); | ||||||
|     } |     } | ||||||
|     if (code == 0xeb14) { |     if (code == 0xeb14) { | ||||||
|       next_d.drive_type = "IDE PATAPI"; |       next_d.drive_type = "IDE PATAPI"; | ||||||
|  | @ -181,7 +181,7 @@ static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { | ||||||
| 
 | 
 | ||||||
|   //in the future, maybe add support for 48-bit LBA, and/or CHS addressing
 |   //in the future, maybe add support for 48-bit LBA, and/or CHS addressing
 | ||||||
|   if (!ids.max_lba) |   if (!ids.max_lba) | ||||||
|     panic("Encountered ATA drive that doesn't support 28-bit LBA"); |     PANIC("Encountered ATA drive that doesn't support 28-bit LBA."); | ||||||
|   next_d.n_sectors = ids.max_lba; |   next_d.n_sectors = ids.max_lba; | ||||||
| 
 | 
 | ||||||
|   commit_drive(next_d); |   commit_drive(next_d); | ||||||
|  |  | ||||||
|  | @ -7,12 +7,11 @@ | ||||||
| #include "task.h" | #include "task.h" | ||||||
| #include "paging.h" | #include "paging.h" | ||||||
| #include "pmap.h" | #include "pmap.h" | ||||||
|  | #include "kbd.h" | ||||||
| 
 | 
 | ||||||
| enum { | enum { | ||||||
|   IDT_PRESENT = 0x80, |   IDT_PRESENT = 0x80, | ||||||
| 
 |  | ||||||
|   IDT_INT     = 0x0e, |   IDT_INT     = 0x0e, | ||||||
|   IDT_TRAP    = 0x0f |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct idt_entry { | struct idt_entry { | ||||||
|  | @ -55,21 +54,13 @@ static uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t cou | ||||||
|   return count; |   return count; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool sc_start_task(uint32_t drive_number, char *path) { | static bool sc_start_task(uint32_t drive_number, char *path, const char *pass) { | ||||||
|   switch_to_kernel_cr3(); |   switch_to_kernel_cr3(); | ||||||
|   bool result = try_elf_run(drives + drive_number, path); |   bool result = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass); | ||||||
|   switch_to_task_cr3(); |   switch_to_task_cr3(); | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void sc_log_string(char *sz) { |  | ||||||
|   logsz(sz); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static char sc_get_key() { |  | ||||||
|   panic("TODO: get key system call"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void *sc_allocate_ram(uint32_t pages) { | static void *sc_allocate_ram(uint32_t pages) { | ||||||
|   return pd_user_allocate_anywhere_writable(active_task->page_directory, pages); |   return pd_user_allocate_anywhere_writable(active_task->page_directory, pages); | ||||||
| } | } | ||||||
|  | @ -94,7 +85,7 @@ static uint32_t sc_memory_info(enum mi_arg arg) { | ||||||
|   case MI_USER_LEFT: |   case MI_USER_LEFT: | ||||||
|     return user_pages_left; |     return user_pages_left; | ||||||
|   case MI_TASK_LEFT: |   case MI_TASK_LEFT: | ||||||
|     panic("TODO: this process memory left"); |     PANIC("TODO: memory info task left"); | ||||||
|   default: |   default: | ||||||
|     return -1; |     return -1; | ||||||
|   } |   } | ||||||
|  | @ -106,18 +97,21 @@ void const *syscall_table[] = { | ||||||
|   &sc_file_read, |   &sc_file_read, | ||||||
|   &sc_file_get_size, |   &sc_file_get_size, | ||||||
|   &sc_start_task, |   &sc_start_task, | ||||||
|   &sc_log_string, |   &logsz, | ||||||
|   &sc_get_key, |   &get_key_code, | ||||||
|   &sc_allocate_ram, |   &sc_allocate_ram, | ||||||
|   &sc_memory_info |   &sc_memory_info | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef void isr_t; | //these aren't really void (*)()'s, but gcc complains if we take an address of a void, so we give it a type
 | ||||||
|  | typedef void (*isr_t)(); | ||||||
| 
 | 
 | ||||||
| extern isr_t syscall_isr; | extern isr_t syscall_isr; | ||||||
| extern isr_t quit_isr; | extern isr_t quit_isr; | ||||||
| extern isr_t yield_isr; | extern isr_t yield_isr; | ||||||
| 
 | 
 | ||||||
|  | extern isr_t kbd_isr; | ||||||
|  | 
 | ||||||
| static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { | static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { | ||||||
|   idt[n].addr_low = (uint32_t)isr & 0xffff; |   idt[n].addr_low = (uint32_t)isr & 0xffff; | ||||||
|   idt[n].addr_high = (uint32_t)isr >> 16; |   idt[n].addr_high = (uint32_t)isr >> 16; | ||||||
|  | @ -125,6 +119,17 @@ static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { | ||||||
|   idt[n].flags = IDT_PRESENT | (dpl << 5) | IDT_INT; |   idt[n].flags = IDT_PRESENT | (dpl << 5) | IDT_INT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | enum { | ||||||
|  |   PIC_MCMD  = 0x0020, | ||||||
|  |   PIC_MDATA = 0x0021, | ||||||
|  |   PIC_SCMD  = 0x00a0, | ||||||
|  |   PIC_SDATA = 0x00a1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   PIC_RESET = 0x11 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void init_idt() { | void init_idt() { | ||||||
|   for (uint16_t i = 0; i < 256; ++i) { |   for (uint16_t i = 0; i < 256; ++i) { | ||||||
|     idt[i].flags = 0; |     idt[i].flags = 0; | ||||||
|  | @ -135,8 +140,22 @@ void init_idt() { | ||||||
|   register_int(0x38, &quit_isr, 3); |   register_int(0x38, &quit_isr, 3); | ||||||
|   register_int(0x39, &yield_isr, 3); |   register_int(0x39, &yield_isr, 3); | ||||||
| 
 | 
 | ||||||
|   outb(0x0021, 0xff); |   register_int(0x21, &kbd_isr, 0); | ||||||
|   outb(0x00a1, 0xff); | 
 | ||||||
|  |   outb(PIC_MCMD, PIC_RESET); | ||||||
|  |   outb(PIC_SCMD, PIC_RESET); | ||||||
|  | 
 | ||||||
|  |   outb(PIC_MDATA, 0x20); | ||||||
|  |   outb(PIC_SDATA, 0x28); | ||||||
|  | 
 | ||||||
|  |   outb(PIC_MDATA, 0x04); | ||||||
|  |   outb(PIC_SDATA, 0x02); | ||||||
|  | 
 | ||||||
|  |   outb(PIC_MDATA, 0x01); | ||||||
|  |   outb(PIC_SDATA, 0x01); | ||||||
|  | 
 | ||||||
|  |   outb(PIC_MDATA, 0xfd); | ||||||
|  |   outb(PIC_SDATA, 0xff); | ||||||
| 
 | 
 | ||||||
|   asm volatile ( |   asm volatile ( | ||||||
|     "lidt %0" |     "lidt %0" | ||||||
|  |  | ||||||
|  | @ -4,12 +4,15 @@ global syscall_isr | ||||||
| global quit_isr | global quit_isr | ||||||
| global yield_isr | global yield_isr | ||||||
| global _start_user_mode | global _start_user_mode | ||||||
|  | global kbd_isr | ||||||
| 
 | 
 | ||||||
| extern syscall_table | extern syscall_table | ||||||
| extern active_task | extern active_task | ||||||
| 
 | 
 | ||||||
| extern delete_task | extern delete_task | ||||||
| extern advance_active_task | extern advance_active_task | ||||||
|  | extern on_kbd_isr | ||||||
|  | extern make_sure_tasks | ||||||
| 
 | 
 | ||||||
| n_syscalls equ 0x9 | n_syscalls equ 0x9 | ||||||
| 
 | 
 | ||||||
|  | @ -39,6 +42,7 @@ syscall_isr: | ||||||
| quit_isr: | quit_isr: | ||||||
|   push dword [active_task] |   push dword [active_task] | ||||||
|   call delete_task |   call delete_task | ||||||
|  |   call make_sure_tasks | ||||||
|   mov dword [esp], yield_isr.return_to_task |   mov dword [esp], yield_isr.return_to_task | ||||||
|   jmp advance_active_task |   jmp advance_active_task | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +63,7 @@ yield_isr: | ||||||
|   mov dword [eax + 4], edx |   mov dword [eax + 4], edx | ||||||
| 
 | 
 | ||||||
|   mov edx, dword [esp + 12] |   mov edx, dword [esp + 12] | ||||||
|   mov dword [eax + 4], edx |   mov dword [eax + 32], edx | ||||||
| 
 | 
 | ||||||
|   call advance_active_task |   call advance_active_task | ||||||
| 
 | 
 | ||||||
|  | @ -72,8 +76,8 @@ yield_isr: | ||||||
|   mov edx, dword [eax + 4] |   mov edx, dword [eax + 4] | ||||||
|   mov cr3, edx |   mov cr3, edx | ||||||
| 
 | 
 | ||||||
|   mov edx, dword [eax + 4] |   mov edx, dword [eax + 32] | ||||||
|   mov dword [esp + 24], edx |   mov dword [esp + 12], edx | ||||||
| 
 | 
 | ||||||
|   mov ebx, dword [eax +  8] |   mov ebx, dword [eax +  8] | ||||||
|   mov ecx, dword [eax + 12] |   mov ecx, dword [eax + 12] | ||||||
|  | @ -95,3 +99,18 @@ _start_user_mode: | ||||||
|   push dword 0x23 |   push dword 0x23 | ||||||
|   sub esp, 4 |   sub esp, 4 | ||||||
|   jmp yield_isr.return_to_task |   jmp yield_isr.return_to_task | ||||||
|  | 
 | ||||||
|  | kbd_isr: | ||||||
|  |   push eax | ||||||
|  |   push ecx | ||||||
|  |   push edx | ||||||
|  | 
 | ||||||
|  |   call on_kbd_isr | ||||||
|  | 
 | ||||||
|  |   mov al, 0x20 | ||||||
|  |   out 0x0020, al | ||||||
|  | 
 | ||||||
|  |   pop edx | ||||||
|  |   pop ecx | ||||||
|  |   pop eax | ||||||
|  |   iret | ||||||
							
								
								
									
										285
									
								
								src/kernel/kbd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								src/kernel/kbd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,285 @@ | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include "panic.h" | ||||||
|  | #include "log.h" | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | static uint32_t *kbd_in_pointer; | ||||||
|  | static uint32_t *kbd_out_pointer; | ||||||
|  | 
 | ||||||
|  | #define KBD_BUFFER_LENGTH 1024 | ||||||
|  | static uint32_t kbd_buffer[KBD_BUFFER_LENGTH]; | ||||||
|  | 
 | ||||||
|  | static uint32_t mod_mask; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   PS2_CMD  = 0x64, | ||||||
|  |   PS2_DATA = 0x60 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   PS2C_READ_CONFIG  = 0x20, | ||||||
|  |   PS2C_WRITE_CONFIG = 0x60, | ||||||
|  |   PS2C_DISABLE      = 0xad, | ||||||
|  |   PS2C_ENABLE       = 0xae | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   PS2S_CODE_READY = 0x01 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   PS2G_XT_COMPAT = 0x40 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void init_kbd() { | ||||||
|  |   outb(PS2_CMD, PS2C_READ_CONFIG); | ||||||
|  |   uint8_t config = inb(PS2_DATA); | ||||||
|  |   outb(PS2_CMD, PS2C_WRITE_CONFIG); | ||||||
|  |   outb(PS2_DATA, config | PS2G_XT_COMPAT); | ||||||
|  | 
 | ||||||
|  |   kbd_in_pointer = kbd_buffer; | ||||||
|  |   kbd_out_pointer = kbd_buffer; | ||||||
|  |   mod_mask = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t get_key_code() { | ||||||
|  |   if (kbd_in_pointer == kbd_out_pointer) | ||||||
|  |     return 0; | ||||||
|  |   uint32_t code = *kbd_out_pointer; | ||||||
|  |   if (++kbd_out_pointer == kbd_buffer + KBD_BUFFER_LENGTH) | ||||||
|  |     kbd_out_pointer = kbd_buffer; | ||||||
|  |   return code; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   MOD_LSHIFT = 0x00100, | ||||||
|  |   MOD_RSHIFT = 0x00200, | ||||||
|  |   MOD_CAPS   = 0x00400, | ||||||
|  |   MOD_INSERT = 0x00800, | ||||||
|  |   MOD_NUMPAD = 0x01000, | ||||||
|  |   MOD_SCROLL = 0x02000, | ||||||
|  |   MOD_LALT   = 0x04000, | ||||||
|  |   MOD_RALT   = 0x08000, | ||||||
|  |   MOD_LCTRL  = 0x10000, | ||||||
|  |   MOD_RCTRL  = 0x20000, | ||||||
|  |   MOD_LMETA  = 0x40000, | ||||||
|  |   MOD_RMETA  = 0x80000 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  |   CODE_CAPS = 0x80, | ||||||
|  |   CODE_INSERT, | ||||||
|  |   CODE_NUMPAD, | ||||||
|  |   CODE_SCROLL, | ||||||
|  |   CODE_LSHIFT, | ||||||
|  |   CODE_RSHIFT, | ||||||
|  |   CODE_LALT, | ||||||
|  |   CODE_RALT, | ||||||
|  |   CODE_LCTRL, | ||||||
|  |   CODE_RCTRL, | ||||||
|  |   CODE_LMETA, | ||||||
|  |   CODE_RMETA, | ||||||
|  |   /* 0x8c - 0x97 reserved */ | ||||||
|  |   /* 0x98 - 0x9f unassigned */ | ||||||
|  |   CODE_F1 = 0xa0, | ||||||
|  |   CODE_F2, | ||||||
|  |   CODE_F3, | ||||||
|  |   CODE_F4, | ||||||
|  |   CODE_F5, | ||||||
|  |   CODE_F6, | ||||||
|  |   CODE_F7, | ||||||
|  |   CODE_F8, | ||||||
|  |   CODE_F9, | ||||||
|  |   CODE_F10, | ||||||
|  |   CODE_F11, | ||||||
|  |   CODE_F12, | ||||||
|  |   /* 0xac - 0xaf unassigned */ | ||||||
|  |   CODE_NUM0 = 0xb0, | ||||||
|  |   CODE_NUM1, | ||||||
|  |   CODE_NUM2, | ||||||
|  |   CODE_NUM3, | ||||||
|  |   CODE_NUM4, | ||||||
|  |   CODE_NUM5, | ||||||
|  |   CODE_NUM6, | ||||||
|  |   CODE_NUM7, | ||||||
|  |   CODE_NUM8, | ||||||
|  |   CODE_NUM9, | ||||||
|  |   CODE_NTIMES, | ||||||
|  |   CODE_NPLUS, | ||||||
|  |   CODE_NENTER, | ||||||
|  |   CODE_NMINUS, | ||||||
|  |   CODE_NDOT, | ||||||
|  |   CODE_NSLASH, | ||||||
|  |   /* 0xc0 unassigned */ | ||||||
|  |   CODE_DELETE, | ||||||
|  |   CODE_HOME, | ||||||
|  |   CODE_END, | ||||||
|  |   CODE_PUP, | ||||||
|  |   CODE_PDOWN, | ||||||
|  |   CODE_UP, | ||||||
|  |   CODE_DOWN, | ||||||
|  |   CODE_LEFT, | ||||||
|  |   CODE_RIGHT, | ||||||
|  |   CODE_ESC, | ||||||
|  |   CODE_MENU, | ||||||
|  |   CODE_PAUSE, | ||||||
|  |   CODE_PRSCR, | ||||||
|  |   /* 0xce - 0xef unassigned */ | ||||||
|  |   CODE_END_LSHIFT = 0xf0, | ||||||
|  |   CODE_END_RSHIFT, | ||||||
|  |   CODE_END_LALT, | ||||||
|  |   CODE_END_RALT, | ||||||
|  |   CODE_END_LCTRL, | ||||||
|  |   CODE_END_RCTRL, | ||||||
|  |   CODE_END_LMETA, | ||||||
|  |   CODE_END_RMETA | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const uint32_t mod_bits[] = { | ||||||
|  |   MOD_CAPS, | ||||||
|  |   MOD_INSERT, | ||||||
|  |   MOD_NUMPAD, | ||||||
|  |   MOD_SCROLL, | ||||||
|  |   MOD_LSHIFT, | ||||||
|  |   MOD_RSHIFT, | ||||||
|  |   MOD_LALT, | ||||||
|  |   MOD_RALT, | ||||||
|  |   MOD_LCTRL, | ||||||
|  |   MOD_RCTRL, | ||||||
|  |   MOD_LMETA, | ||||||
|  |   MOD_RMETA | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const uint32_t *const unmod_bits = mod_bits + 4; | ||||||
|  | 
 | ||||||
|  | //in these tables, 0x00 represents an unknown key,
 | ||||||
|  | //             and 0xff represents a key release.
 | ||||||
|  | 
 | ||||||
|  | static const uint8_t codes[] = { | ||||||
|  |   0,         CODE_ESC,  '1',         '2',       '3',       '4',         '5',         '6', | ||||||
|  |   '7',       '8',       '9',         '0',       '-',       '=',         '\b',        '\t', | ||||||
|  |   'q',       'w',       'e',         'r',       't',       'y',         'u',         'i', | ||||||
|  |   'o',       'p',       '[',         ']',       '\n',      CODE_LCTRL,  'a',         's', | ||||||
|  |   'd',       'f',       'g',         'h',       'j',       'k',         'l',         ';', | ||||||
|  |   '\'',      '`',       CODE_LSHIFT, '\\',      'z',       'x',         'c',         'v', | ||||||
|  |   'b',       'n',       'm',         ',',       '.',       '/',         CODE_RSHIFT, CODE_NTIMES, | ||||||
|  |   CODE_LALT, ' ',       CODE_CAPS,   CODE_F1,   CODE_F2,   CODE_F3,     CODE_F4,     CODE_F5, | ||||||
|  |   CODE_F6,   CODE_F7,   CODE_F8,     CODE_F9,   CODE_F10,  CODE_NUMPAD, CODE_SCROLL, CODE_NUM7, | ||||||
|  |   CODE_NUM8, CODE_NUM9, CODE_NMINUS, CODE_NUM4, CODE_NUM5, CODE_NUM6,   CODE_NPLUS,  CODE_NUM1, | ||||||
|  |   CODE_NUM2, CODE_NUM3, CODE_NUM0,   CODE_NDOT, 0,         0,           0,           CODE_F11, | ||||||
|  |   CODE_F12,  0,         0,           0,         0,         0,           0,           0, | ||||||
|  |   0,         0,         0,           0,         0,         0,           0,           0, | ||||||
|  |   0,         0,         0,           0,         0,         0,           0,           0, | ||||||
|  |   0,         0,         0,           0,         0,         0,           0,           0, | ||||||
|  |   0,         0,         0,           0,         0,         0,           0,           0, | ||||||
|  | 
 | ||||||
|  |   0,             0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, CODE_END_LCTRL, 0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, CODE_END_LSHIFT, 0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           CODE_END_RSHIFT, 0xff, | ||||||
|  |   CODE_END_LALT, 0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0xff, 0xff,           0xff,            0xff, | ||||||
|  |   0xff,          0xff, 0xff,            0xff, 0,    0,              0,               0xff, | ||||||
|  |   0xff,          0,    0,               0,    0,    0,              0,               0, | ||||||
|  |   0,             0,    0,               0,    0,    0,              0,               0, | ||||||
|  |   0,             0,    0,               0,    0,    0,              0,               0, | ||||||
|  |   0,             0,    0,               0,    0,    0,              0,               0, | ||||||
|  |   0,             0,    0,               0,    0,    0,              0,               0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const uint8_t codes_e0[] = { | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           CODE_NENTER, CODE_RCTRL,  0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           CODE_NSLASH, 0, 0, | ||||||
|  |   CODE_RALT, 0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, CODE_HOME, | ||||||
|  |   CODE_UP,   CODE_PUP,   0,           CODE_LEFT,   0,           CODE_RIGHT,  0, CODE_END, | ||||||
|  |   CODE_DOWN, CODE_PDOWN, CODE_INSERT, CODE_DELETE, 0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           CODE_LMETA,  CODE_RMETA,  CODE_MENU,   0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  |   0,         0,          0,           0,           0,           0,           0, 0, | ||||||
|  | 
 | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0xff,           CODE_END_RCTRL, 0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0xff,           0, 0, | ||||||
|  |   CODE_END_RALT, 0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0xff, | ||||||
|  |   0xff,          0xff, 0,    0xff,           0,              0xff,           0, 0xff, | ||||||
|  |   0xff,          0xff, 0xff, 0xff,           0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    CODE_END_LMETA, CODE_END_RMETA, 0xff,           0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0, | ||||||
|  |   0,             0,    0,    0,              0,              0,              0, 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void on_kbd_isr() { | ||||||
|  |   while (inb(PS2_CMD) & PS2S_CODE_READY) { | ||||||
|  |     uint8_t code = inb(PS2_DATA); | ||||||
|  |     if (code == 0xe1) { | ||||||
|  |       code = inb(PS2_DATA); | ||||||
|  |       if (code == 0x1d) { | ||||||
|  |         if (inb(PS2_DATA) != 0x45) | ||||||
|  |           code = 0; | ||||||
|  |         else | ||||||
|  |           code = CODE_PAUSE; | ||||||
|  |       } | ||||||
|  |       else if (code == 0x9d) { | ||||||
|  |         if (inb(PS2_DATA) != 0xc5) | ||||||
|  |           code = 0; | ||||||
|  |         else | ||||||
|  |           code = 0xff; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         code = 0; | ||||||
|  |     } | ||||||
|  |     else if (code == 0xe0) { | ||||||
|  |       code = inb(PS2_DATA); | ||||||
|  |       if (code == 0x2a) { | ||||||
|  |         if ((inb(PS2_DATA) != 0xe0) || | ||||||
|  |             (inb(PS2_DATA) != 0x37)) | ||||||
|  |           code = 0; | ||||||
|  |         else | ||||||
|  |           code = CODE_PRSCR; | ||||||
|  |       } | ||||||
|  |       else if (code == 0xb7) { | ||||||
|  |         if ((inb(PS2_DATA) != 0xe0) || | ||||||
|  |             (inb(PS2_DATA) != 0xaa)) | ||||||
|  |           code = 0; | ||||||
|  |         else | ||||||
|  |           code = 0xff; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |         code = codes_e0[code]; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |       code = codes[code]; | ||||||
|  | 
 | ||||||
|  |     if (!code) | ||||||
|  |       PANIC("Unknown scancode."); | ||||||
|  | 
 | ||||||
|  |     if (code < 0xf0) | ||||||
|  |       *kbd_in_pointer++ = mod_mask | code; | ||||||
|  |     if ((code >= 0x80) && (code <= 0x83)) | ||||||
|  |       mod_mask ^= mod_bits[code & 0x03]; | ||||||
|  |     else if ((code >= 0x84) && (code <= 0x8b)) | ||||||
|  |       mod_mask |= mod_bits[code & 0x0f]; | ||||||
|  |     else if (code >= 0xf0) | ||||||
|  |       mod_mask &= ~unmod_bits[code & 0x0f]; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								src/kernel/kbd.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/kernel/kbd.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | #ifndef KBD_H | ||||||
|  | #define KBD_H | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | void init_kbd(); | ||||||
|  | uint32_t get_key_code(); | ||||||
|  | void on_kbd_isr(); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| #include "elf.h" | #include "elf.h" | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "vga.h" | #include "vga.h" | ||||||
|  | #include "kbd.h" | ||||||
| 
 | 
 | ||||||
| void reset_tree(); | void reset_tree(); | ||||||
| void tree(struct drive *d); | void tree(struct drive *d); | ||||||
|  | @ -32,8 +33,6 @@ void main() { | ||||||
| 
 | 
 | ||||||
|   logsz("Portland v0.0.11\n\n"); |   logsz("Portland v0.0.11\n\n"); | ||||||
| 
 | 
 | ||||||
|   //list vesa modes?
 |  | ||||||
| 
 |  | ||||||
|   pci_init(); |   pci_init(); | ||||||
| 
 | 
 | ||||||
|   u16_dec(n_pci_devices, nbuf); |   u16_dec(n_pci_devices, nbuf); | ||||||
|  | @ -137,9 +136,10 @@ void main() { | ||||||
|   logsz(nbuf); |   logsz(nbuf); | ||||||
|   logsz("k\n\n"); |   logsz("k\n\n"); | ||||||
| 
 | 
 | ||||||
|   if (!try_elf_run(drives, "BIN/INIT.ELF")) |   if (!try_elf_run(drives, "BIN/INIT.ELF", "")) | ||||||
|     panic("Failed to load init program."); |     PANIC("Failed to load init program."); | ||||||
| 
 | 
 | ||||||
|  |   init_kbd(); | ||||||
|   init_idt(); |   init_idt(); | ||||||
| 
 | 
 | ||||||
|   logsz("Switching to init task.\n"); |   logsz("Switching to init task.\n"); | ||||||
|  |  | ||||||
|  | @ -77,25 +77,45 @@ void *new_task_pd() { | ||||||
| void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable) { | void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable) { | ||||||
|   void *pma = allocate_user_pages(pages); |   void *pma = allocate_user_pages(pages); | ||||||
|   if (!pma) |   if (!pma) | ||||||
|     panic("Could not allocate user pages."); |     PANIC("Could not allocate user pages."); | ||||||
|   for (uint32_t i = 0; i < pages; ++i) |   for (uint32_t i = 0; i < pages; ++i) | ||||||
|     pd_map(pd, (uint32_t)pma + (i << 12), vma + (i << 12), writable); |     pd_map(pd, (uint32_t)pma + (i << 12), vma + (i << 12), writable); | ||||||
|   return pma; |   return pma; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages) { | __attribute__ ((pure)) | ||||||
|  | static void *find_user_vma_run(void *pd, uint32_t pages) { | ||||||
|   uint32_t run = 0; |   uint32_t run = 0; | ||||||
|   for (void *vma = (void *)KERNEL_END; vma; vma += 4096) { |   for (void *vma = (void *)KERNEL_END; vma; vma += 4096) { | ||||||
|     if (pd_is_mapped(pd, (uint32_t)vma)) |     if (pd_is_mapped(pd, (uint32_t)vma)) | ||||||
|       run = 0; |       run = 0; | ||||||
|     else if (++run == pages) { |     else if (++run == pages) | ||||||
|       vma -= (pages - 1) * 4096; |       return vma - (pages - 1) * 4096; | ||||||
|  |   } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages) { | ||||||
|  |   void *vma = find_user_vma_run(pd, pages); | ||||||
|  |   if (!vma) | ||||||
|  |     return 0; | ||||||
|   for (uint32_t i = 0; i < pages; ++i) |   for (uint32_t i = 0; i < pages; ++i) | ||||||
|     pd_map(pd, (uint32_t)allocate_user_pages(1), (uint32_t)vma + 4096 * i, true); |     pd_map(pd, (uint32_t)allocate_user_pages(1), (uint32_t)vma + 4096 * i, true); | ||||||
|   return vma; |   return vma; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **vma_out, void **pma_out) { | ||||||
|  |   *vma_out = find_user_vma_run(pd, pages); | ||||||
|  |   if (!*vma_out) { | ||||||
|  |     *pma_out = 0; | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|  |   *pma_out = allocate_user_pages(pages); | ||||||
|  |   if (!*pma_out) { | ||||||
|  |     *vma_out = 0; | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   return 0; |   pd_map(pd, (uint32_t)*pma_out, (uint32_t)*vma_out, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define KPAGE_DIR     ((uint32_t *)0x00005000) | #define KPAGE_DIR     ((uint32_t *)0x00005000) | ||||||
|  | @ -118,6 +138,11 @@ void init_paging() { | ||||||
|   : : : "eax"); |   : : : "eax"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | __attribute__ ((pure)) | ||||||
|  | void *vma_to_pma(void *pd, const void *vma) { | ||||||
|  |   return (void *)(((uint32_t *)(((uint32_t *)pd)[(uint32_t)vma >> 22] & PE_ADDR_MASK))[((uint32_t)vma >> 12) % 1024] & PE_ADDR_MASK) + (uint32_t)vma % 4096; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void switch_to_kernel_cr3() { | void switch_to_kernel_cr3() { | ||||||
|   asm volatile ( |   asm volatile ( | ||||||
|     "mov $0x00005000, %%eax\n" |     "mov $0x00005000, %%eax\n" | ||||||
|  |  | ||||||
|  | @ -11,6 +11,9 @@ void free_task_pd(void *pd); | ||||||
| void *new_task_pd(); | void *new_task_pd(); | ||||||
| void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable); | void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable); | ||||||
| void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages); | void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages); | ||||||
|  | void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **vma_out, void **pma_out); | ||||||
|  | 
 | ||||||
|  | void *vma_to_pma(void *pd, const void *vma) __attribute__ ((pure)); | ||||||
| 
 | 
 | ||||||
| void switch_to_kernel_cr3(); | void switch_to_kernel_cr3(); | ||||||
| void switch_to_task_cr3(); | void switch_to_task_cr3(); | ||||||
|  | @ -1,11 +1,17 @@ | ||||||
| #include "panic.h" |  | ||||||
| #include "log.h" | #include "log.h" | ||||||
| #include "vga.h" | #include "vga.h" | ||||||
|  | #include "util.h" | ||||||
| 
 | 
 | ||||||
| void panic(const char *message) { | __attribute__ ((noreturn)) | ||||||
|  | void panic(const char *filename, uint32_t line, const char *message) { | ||||||
|   set_log_mode(LOG_PANIC); |   set_log_mode(LOG_PANIC); | ||||||
|   vga_blank(); |   vga_blank(); | ||||||
|   logsz("Kernel panic: "); |   logsz("Kernel panic ["); | ||||||
|  |   logsz(filename); | ||||||
|  |   char nbuf[12] = ":"; | ||||||
|  |   u32_dec(line, nbuf + 1); | ||||||
|  |   logsz(nbuf); | ||||||
|  |   logsz("]: "); | ||||||
|   logsz(message); |   logsz(message); | ||||||
|   logsz("\nHalting."); |   logsz("\nHalting."); | ||||||
|   while (1) |   while (1) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,10 @@ | ||||||
| #ifndef PANIC_H | #ifndef PANIC_H | ||||||
| #define PANIC_H | #define PANIC_H | ||||||
| 
 | 
 | ||||||
| void panic(const char *message) __attribute__ ((noreturn)); | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | #define PANIC(msg) panic(__FILE__, __LINE__, msg) | ||||||
|  | 
 | ||||||
|  | void panic(const char *filename, uint32_t line, const char *message) __attribute__ ((noreturn)); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -32,7 +32,7 @@ struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_ | ||||||
| static struct pci_device *next_pci_device() { | static struct pci_device *next_pci_device() { | ||||||
|   if (!(n_pci_devices % PCI_DEVICES_PER_PAGE)) |   if (!(n_pci_devices % PCI_DEVICES_PER_PAGE)) | ||||||
|     if (!(pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_kernel_pages(1))) |     if (!(pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_kernel_pages(1))) | ||||||
|       panic("Out of memory in PCI enumeration"); |       PANIC("Out of memory in PCI enumeration."); | ||||||
|   return nth_pci_device(n_pci_devices++); |   return nth_pci_device(n_pci_devices++); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -64,9 +64,9 @@ static void pci_device_check(uint16_t number) { | ||||||
| 
 | 
 | ||||||
| void pci_init() { | void pci_init() { | ||||||
|   if (!(BOOT_INFO->support_flags & BIS_PCI)) |   if (!(BOOT_INFO->support_flags & BIS_PCI)) | ||||||
|     panic("No PCI support detected."); |     PANIC("No PCI support detected."); | ||||||
|   if (!(BOOT_INFO->pci_hw_char & PHC_CS_M1)) |   if (!(BOOT_INFO->pci_hw_char & PHC_CS_M1)) | ||||||
|     panic("No PCI Mechanism 1 support"); |     PANIC("No PCI Mechanism 1 support."); | ||||||
| 
 | 
 | ||||||
|   n_pci_devices = 0; |   n_pci_devices = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -70,22 +70,24 @@ void new_task(struct task_state state) { | ||||||
|       tasks[n] = state; |       tasks[n] = state; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   panic("Maximum number of tasks reached."); |   PANIC("Maximum number of tasks reached."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void advance_active_task() { | void advance_active_task() { | ||||||
|   struct task_state *prev_task = active_task; |   do | ||||||
|   do { |  | ||||||
|     if (++active_task == tasks + MAX_TASKS) |     if (++active_task == tasks + MAX_TASKS) | ||||||
|       active_task = tasks; |       active_task = tasks; | ||||||
|     if (active_task == prev_task) { |   while (!active_task->page_directory); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void make_sure_tasks() { | ||||||
|  |   for (uint8_t n = 0; n < MAX_TASKS; ++n) | ||||||
|  |     if (tasks[n].page_directory) | ||||||
|  |       return; | ||||||
|   set_log_mode(LOG_SYSTEM); |   set_log_mode(LOG_SYSTEM); | ||||||
|   logsz("No active tasks, halting."); |   logsz("No active tasks, halting."); | ||||||
|   while (1) |   while (1) | ||||||
|     asm ("hlt"); |     asm ("hlt"); | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   while (!active_task->page_directory); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void delete_task(struct task_state *state) { | void delete_task(struct task_state *state) { | ||||||
|  |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| #include <knob/user.h> |  | ||||||
| 
 |  | ||||||
| void main() { |  | ||||||
|   tell_user_sz("Hello, world!\n"); |  | ||||||
| } |  | ||||||
							
								
								
									
										21
									
								
								src/user/highway/highway.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/user/highway/highway.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | #include <knob/user.h> | ||||||
|  | #include <knob/task.h> | ||||||
|  | #include <knob/block.h> | ||||||
|  | 
 | ||||||
|  | //TODO: load a user environment file containing a PATH-like setting.
 | ||||||
|  | //TODO: have an active disk and/or directory
 | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |   char path_buf[1024 + 4] = "BIN/"; | ||||||
|  |   char *const line_buf = path_buf + 4; | ||||||
|  |   while (1) { | ||||||
|  |     tell_user_sz("> "); | ||||||
|  |     ask_user_line_sz(line_buf, 1023); | ||||||
|  |     if (blockequ(line_buf, "exit", 5)) | ||||||
|  |       return; | ||||||
|  |     if (try_run_command(path_buf)) | ||||||
|  |       yield_task(); | ||||||
|  |     else | ||||||
|  |       tell_user_sz("An error occured trying to run that command.\n"); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								src/user/include/knob/block.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/user/include/knob/block.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | #ifndef KNOB_BLOCK_H | ||||||
|  | #define KNOB_BLOCK_H | ||||||
|  | 
 | ||||||
|  | void blockcpy(void *to, const void *from, uint32_t size); | ||||||
|  | bool blockequ(void *a, void *b, uint32_t size) __attribute__ ((__pure__)); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -6,7 +6,8 @@ | ||||||
| void tell_user_sz(const char *sz); | void tell_user_sz(const char *sz); | ||||||
| void tell_user_n(uint32_t n); | void tell_user_n(uint32_t n); | ||||||
| 
 | 
 | ||||||
| //return value and max_length both include null terminator
 | //return value and max_length don't include null terminator
 | ||||||
|  | //returns the real length of the string
 | ||||||
| uint32_t ask_user_line_sz(char *sz, uint32_t max_length); | uint32_t ask_user_line_sz(char *sz, uint32_t max_length); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | @ -97,7 +97,7 @@ static inline uint32_t _sc5(enum _scn eax, uint32_t ebx, uint32_t ecx, uint32_t | ||||||
| static inline void _yield_task() { | static inline void _yield_task() { | ||||||
|   asm ( |   asm ( | ||||||
|     "int $0x39" |     "int $0x39" | ||||||
|   ); |   : : : "eax"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __attribute__ ((noreturn)) | __attribute__ ((noreturn)) | ||||||
|  | @ -124,8 +124,8 @@ static inline uint32_t _file_size(_file_handle_t handle) { | ||||||
|   return _sc1(_SCN_FILE_SIZE, handle); |   return _sc1(_SCN_FILE_SIZE, handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline bool _start_task(_drive_number_t drive_number, const char *path) { | static inline bool _start_task(_drive_number_t drive_number, const char *path, const char *pass) { | ||||||
|   return (bool)_sc2(_SCN_START_TASK, drive_number, (uint32_t)path); |   return (bool)_sc3(_SCN_START_TASK, drive_number, (uint32_t)path, (uint32_t)pass); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void _log_string(const char *sz) { | static inline void _log_string(const char *sz) { | ||||||
|  |  | ||||||
|  | @ -2,13 +2,27 @@ | ||||||
| #include <knob/file.h> | #include <knob/file.h> | ||||||
| #include <knob/task.h> | #include <knob/task.h> | ||||||
| 
 | 
 | ||||||
|  | void start(const char *cmd) { | ||||||
|  |   tell_user_sz(cmd); | ||||||
|  |   tell_user_sz(": "); | ||||||
|  |   tell_user_sz( | ||||||
|  |     try_run_command(cmd) | ||||||
|  |       ? "success\n" | ||||||
|  |       : "failed\n" | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define STARTUP_FILE_PATH "SYS/STARTUP.RC" | ||||||
|  | 
 | ||||||
| void main() { | void main() { | ||||||
|   struct file *f = open_file("SYS/STARTUP.RC"); |   struct file *f = open_file(STARTUP_FILE_PATH); | ||||||
|   if (!f) { |   if (!f) { | ||||||
|     tell_user_sz("Could not open SYS/STARTUP.RC\n"); |     tell_user_sz("Could not open " STARTUP_FILE_PATH "\n"); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   tell_user_sz("[init] Reading from " STARTUP_FILE_PATH ":\n"); | ||||||
|  | 
 | ||||||
|   char buf[1024]; |   char buf[1024]; | ||||||
|   char *bufp = buf; |   char *bufp = buf; | ||||||
|   while (read_from_file(f, 1, bufp)) { |   while (read_from_file(f, 1, bufp)) { | ||||||
|  | @ -16,7 +30,7 @@ void main() { | ||||||
|       if (bufp == buf) |       if (bufp == buf) | ||||||
|         continue; |         continue; | ||||||
|       *bufp = '\0'; |       *bufp = '\0'; | ||||||
|       try_run_command(buf); |       start(buf); | ||||||
|       bufp = buf; |       bufp = buf; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|  | @ -24,8 +38,10 @@ void main() { | ||||||
|   } |   } | ||||||
|   if (bufp != buf) { |   if (bufp != buf) { | ||||||
|     *bufp = '\0'; |     *bufp = '\0'; | ||||||
|     try_run_command(buf); |     start(buf); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   close_file(f); |   close_file(f); | ||||||
|  | 
 | ||||||
|  |   tell_user_sz("[init] Done.\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								src/user/knob/block.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/user/knob/block.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | 
 | ||||||
|  | //unsophisticated, should copy by dwords where available
 | ||||||
|  | void blockcpy(void *to, const void *from, uint32_t size) { | ||||||
|  |   for (uint32_t i = 0; i < size; ++i) | ||||||
|  |     *(uint8_t *)(to++) = *(const uint8_t *)(from++); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //unsophisticated, should check by dwords wheere available
 | ||||||
|  | __attribute__ ((__pure__)) | ||||||
|  | bool blockequ(void *a, void *b, uint32_t size) { | ||||||
|  |   for (uint32_t i = 0; i < size; ++i) | ||||||
|  |     if (*(uint8_t *)(a++) != *(uint8_t *)(b++)) | ||||||
|  |       return false; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  | @ -10,6 +10,7 @@ extern current_disk | ||||||
| section .text | section .text | ||||||
| _entry: | _entry: | ||||||
|   mov esp, stack |   mov esp, stack | ||||||
|  |   push edx | ||||||
| 
 | 
 | ||||||
|   ;TODO: heap stuff? |   ;TODO: heap stuff? | ||||||
|   ;TODO: determine current_disk |   ;TODO: determine current_disk | ||||||
|  |  | ||||||
|  | @ -1,29 +1,6 @@ | ||||||
| #include <pland/syscall.h> | #include <pland/syscall.h> | ||||||
| #include <knob/heap.h> |  | ||||||
| 
 |  | ||||||
| struct quit_list_node { |  | ||||||
|   struct quit_list_node *prev; |  | ||||||
|   void (*f)(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static struct quit_list_node head = { |  | ||||||
|   .f = &_exit_task |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static struct quit_list_node *last = &head; |  | ||||||
| 
 |  | ||||||
| void on_quit(void (*run_f)()) { |  | ||||||
|   struct quit_list_node *new = get_block(sizeof(struct quit_list_node)); |  | ||||||
|   new->prev = last; |  | ||||||
|   new->f = run_f; |  | ||||||
|   last = new; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| __attribute__ ((noreturn)) | __attribute__ ((noreturn)) | ||||||
| void quit() { | void quit() { | ||||||
|   struct quit_list_node *node = last; |   _exit_task(); | ||||||
|   while (1) { |  | ||||||
|     node->f(); |  | ||||||
|     node = node->prev; |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | @ -1,11 +1,25 @@ | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <pland/syscall.h> | #include <pland/syscall.h> | ||||||
| #include <knob/file.h> | #include <knob/file.h> | ||||||
|  | #include <knob/heap.h> | ||||||
|  | #include <knob/block.h> | ||||||
| 
 | 
 | ||||||
| bool try_run_command(const char *path) { | bool try_run_command(const char *path) { | ||||||
|   uint8_t dn; |   uint8_t dn; | ||||||
|   path = remove_prefix(path, &dn); |   path = remove_prefix(path, &dn); | ||||||
|   return _start_task(dn, path); | 
 | ||||||
|  |   for (const char *ptr = path; *ptr; ++ptr) | ||||||
|  |     if (*ptr == ' ') { | ||||||
|  |       char *new_path = get_block(ptr - path + 1); | ||||||
|  |       blockcpy(new_path, path, ptr - path); | ||||||
|  |       new_path[ptr - path] = '\0'; | ||||||
|  | 
 | ||||||
|  |       bool succeded = _start_task(dn, new_path, ptr + 1); | ||||||
|  |       free_block(new_path); | ||||||
|  |       return succeded; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   return _start_task(dn, path, ""); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void yield_task() { | void yield_task() { | ||||||
|  |  | ||||||
|  | @ -19,9 +19,25 @@ static const uint8_t caps_and_shift[] = { | ||||||
|   0x7e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, |   0x7e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | ||||||
|   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, |   0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | ||||||
|   0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, |   0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, | ||||||
|   0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 |   0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, | ||||||
| 
 | 
 | ||||||
|   //TODO: higher
 |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  | 
 | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t caps_no_shift[] = { | static const uint8_t caps_no_shift[] = { | ||||||
|  | @ -41,9 +57,25 @@ static const uint8_t caps_no_shift[] = { | ||||||
|   0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |   0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | ||||||
|   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | ||||||
|   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, | ||||||
|   0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 |   0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, | ||||||
| 
 | 
 | ||||||
|   //TODO: higher
 |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  | 
 | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t shifted[] = { | static const uint8_t shifted[] = { | ||||||
|  | @ -63,28 +95,39 @@ static const uint8_t shifted[] = { | ||||||
|   0x7e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |   0x7e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | ||||||
|   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |   0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | ||||||
|   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, |   0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, | ||||||
|   0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 |   0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, | ||||||
| 
 | 
 | ||||||
|   //TODO: higher
 |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  | 
 | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static char get_key_char() { | static char get_key_char() { | ||||||
|   _key_code_t key; |   _key_code_t key; | ||||||
|   while (!(key = _get_key())) |   while (!(key = _get_key())) | ||||||
|     _yield_task(); |     _yield_task(); | ||||||
|   return (char)( |   return | ||||||
|     (key & (_KEY_ALT | _KEY_CTRL | _KEY_META)) |     key & _KEY_CAPS | ||||||
|     ? 0 |     ? key & _KEY_SHIFT | ||||||
|     : (key & _KEY_CAPS) |  | ||||||
|       ? (key & _KEY_SHIFT) |  | ||||||
|       ? caps_and_shift[key & 0xff] |       ? caps_and_shift[key & 0xff] | ||||||
|       : caps_no_shift[key & 0xff] |       : caps_no_shift[key & 0xff] | ||||||
|       : (key & _KEY_SHIFT) |     : key & _KEY_SHIFT | ||||||
|       ? shifted[key & 0xff] |       ? shifted[key & 0xff] | ||||||
|         : (key & 0x80) |       : key & 0xff; | ||||||
|           ? 0 |  | ||||||
|           : (key & 0x7f) |  | ||||||
|   ); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void tell_user_sz(const char *sz) { | void tell_user_sz(const char *sz) { | ||||||
|  | @ -115,8 +158,14 @@ uint32_t ask_user_line_sz(char *sz, uint32_t max_length) { | ||||||
| 
 | 
 | ||||||
|   uint32_t i; |   uint32_t i; | ||||||
|   for (i = 0; i != max_length; ++i) { |   for (i = 0; i != max_length; ++i) { | ||||||
|     char key = get_key_char(); |     char key; | ||||||
|     if (key) { |   replace: | ||||||
|  |     key = get_key_char(); | ||||||
|  |     if (!key) | ||||||
|  |       goto replace; | ||||||
|  |     if (key & 0x80) | ||||||
|  |       goto replace;//TODO
 | ||||||
|  | 
 | ||||||
|     log_buf[0] = key; |     log_buf[0] = key; | ||||||
|     _log_string(log_buf); |     _log_string(log_buf); | ||||||
| 
 | 
 | ||||||
|  | @ -127,7 +176,6 @@ uint32_t ask_user_line_sz(char *sz, uint32_t max_length) { | ||||||
|     else |     else | ||||||
|       sz[i] = key; |       sz[i] = key; | ||||||
|   } |   } | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   sz[i] = '\0'; |   sz[i] = '\0'; | ||||||
|   return i; |   return i; | ||||||
|  |  | ||||||
		Reference in a new issue