Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
4e76b80f79 |
6
.clang-format
Normal file
6
.clang-format
Normal file
@ -0,0 +1,6 @@
|
||||
UseTab: Never
|
||||
IndentWidth: 2
|
||||
BreakBeforeBraces: Attach
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
ColumnLimit: 0
|
26
.gdbinit
26
.gdbinit
@ -1,3 +1,29 @@
|
||||
set pagination off
|
||||
target remote localhost:1234
|
||||
symbol-file kernel/kernel.elf
|
||||
add-symbol-file vfs/vfs
|
||||
b kernel/tasking.c:226
|
||||
commands 1
|
||||
silent
|
||||
disable breakpoints
|
||||
symbol-file kernel/kernel.elf
|
||||
p current_thread->process->pid
|
||||
if current_thread->process->pid==2
|
||||
add-symbol-file vfs/vfs
|
||||
b main
|
||||
commands
|
||||
p "HIT"
|
||||
disable breakpoints 1
|
||||
end
|
||||
enable breakpoints
|
||||
else
|
||||
enable breakpoints 1
|
||||
c
|
||||
end
|
||||
c
|
||||
end
|
||||
|
||||
# b main
|
||||
# commands
|
||||
# disable breakpoints 1
|
||||
# end
|
||||
|
17
Makefile
17
Makefile
@ -18,7 +18,7 @@ AR = $(shell cat psinfo/$(PLAT)/ar.txt)
|
||||
NASM = $(shell cat psinfo/$(PLAT)/nasm.txt)
|
||||
EMU = $(shell cat psinfo/$(PLAT)/emu.txt)
|
||||
CFLAGS = -Isysroot/usr/include -Wextra -Wall -Wno-unused-parameter -g -ffreestanding
|
||||
QFLAGS = -m 2G -boot d -cdrom os.iso -serial file:serout #-chardev socket,id=s1,port=3000,host=localhost -serial chardev:s1
|
||||
QFLAGS = -m 2G -enable-kvm -boot d -cdrom os.iso -serial file:serout # -chardev socket,server,id=s1,port=3000,host=localhost -serial chardev:s1
|
||||
CWD = $(shell pwd)
|
||||
|
||||
.PHONY: sysroot
|
||||
@ -38,11 +38,12 @@ run_nobuild:
|
||||
tail -f serout
|
||||
|
||||
debug: os.iso kernel/kernel.elf
|
||||
@$(EMU) -s $(QFLAGS) &
|
||||
@$(EMU) -s -S $(QFLAGS) &
|
||||
sleep 2
|
||||
gdb
|
||||
#gdbgui -g i386-elf-gdb --project $(CWD)
|
||||
|
||||
os.iso: kernel/kernel.elf init vfs devfs vga_drv initrd_drv tar_fs pci sysroot/usr/share/man # vfs devfs initrd vga_drv initrd_drv pci
|
||||
os.iso: kernel/kernel.elf init vfs devfs vga_drv initrd_drv tar_fs pci ps2 sysroot/usr/share/man # vfs devfs initrd vga_drv initrd_drv pci
|
||||
@cp kernel/kernel.elf sysroot/boot
|
||||
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
|
||||
@grub-mkrescue -o $@ sysroot
|
||||
@ -50,9 +51,9 @@ os.iso: kernel/kernel.elf init vfs devfs vga_drv initrd_drv tar_fs pci sysroot/u
|
||||
crts: kernel/crt0.o
|
||||
@cp $^ sysroot/usr/lib
|
||||
|
||||
# ps2: crts libc
|
||||
# @cd $@ && make
|
||||
# @cp $@/$@ initrd/$@
|
||||
ps2: crts libc
|
||||
@cd $@ && make
|
||||
@cp $@/$@ initrd/$@
|
||||
|
||||
init: crts libc
|
||||
@cd $@ && make
|
||||
@ -115,8 +116,8 @@ clean:
|
||||
@rm -rf initrd/* kernel/*.o drivers/*/*.o drivers/*/*/*.o cpu/*/*.o fs/*.o libc/libc.a kernel/cstart.o cpu/memory.h os.iso */*.elf sysroot/boot/initrd.tar
|
||||
|
||||
doc: $(C_SOURCES) $(C_HEADERS)
|
||||
@doxygen kernel/Doxyfile > /dev/null
|
||||
@doxygen libc/Doxyfile > /dev/null
|
||||
# @doxygen kernel/Doxyfile > /dev/null
|
||||
# @doxygen libc/Doxyfile > /dev/null
|
||||
|
||||
install:
|
||||
@echo Path to flash drive?; \
|
||||
|
12
Vagrantfile
vendored
12
Vagrantfile
vendored
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
@ -5,14 +7,14 @@
|
||||
# configures the configuration version (we support older styles for
|
||||
# backwards compatibility). Please don't change it unless you know what
|
||||
# you're doing.
|
||||
Vagrant.configure("2") do |config|
|
||||
Vagrant.configure('2') do |config|
|
||||
# The most common configuration options are documented and commented below.
|
||||
# For a complete reference, please see the online documentation at
|
||||
# https://docs.vagrantup.com.
|
||||
|
||||
# Every Vagrant development environment requires a box. You can search for
|
||||
# boxes at https://vagrantcloud.com/search.
|
||||
config.vm.box = "ubuntu/bionic64"
|
||||
config.vm.box = 'ubuntu/bionic64'
|
||||
|
||||
# Disable automatic box update checking. If you disable this, then
|
||||
# boxes will only be checked for updates when the user runs
|
||||
@ -49,12 +51,12 @@ Vagrant.configure("2") do |config|
|
||||
# backing providers for Vagrant. These expose provider-specific options.
|
||||
# Example for VirtualBox:
|
||||
#
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
config.vm.provider 'virtualbox' do |vb|
|
||||
# Do not display the VirtualBox GUI when booting the machine
|
||||
vb.gui = false
|
||||
|
||||
# Customize the amount of memory on the VM:
|
||||
vb.memory = "4096"
|
||||
vb.memory = '4096'
|
||||
end
|
||||
#
|
||||
# View the documentation for the provider you are using for more
|
||||
@ -63,7 +65,7 @@ Vagrant.configure("2") do |config|
|
||||
# Enable provisioning with a shell script. Additional provisioners such as
|
||||
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
||||
# documentation for more information about their specific syntax and use.
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
config.vm.provision 'shell', inline: <<-SHELL
|
||||
apt install ruby
|
||||
SHELL
|
||||
end
|
||||
|
956
init/i386_stub.cold
Normal file
956
init/i386_stub.cold
Normal file
@ -0,0 +1,956 @@
|
||||
/*/*****************************************************************************/
|
||||
|
||||
/* THIS SOFTWARE IS NOT COPYRIGHTED*/
|
||||
|
||||
/* HP offers the following for use in the public domain. HP makes no*/
|
||||
/* warranty with regard to the software or it's performance and the*/
|
||||
/* user accepts the software "AS IS" with all faults.*/
|
||||
|
||||
/* HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD*/
|
||||
/* TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES*/
|
||||
/* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.*/
|
||||
|
||||
/*****************************************************************************/*/
|
||||
|
||||
/*/*****************************************************************************/
|
||||
/* * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $*/
|
||||
/* **/
|
||||
/* * Module name: remcom.c $*/
|
||||
/* * Revision: 1.34 $*/
|
||||
/* * Date: 91/03/09 12:29:49 $*/
|
||||
/* * Contributor: Lake Stevens Instrument Division$*/
|
||||
/* **/
|
||||
/* * Description: low level support for gdb debugger. $*/
|
||||
/* **/
|
||||
/* * Considerations: only works on target hardware $*/
|
||||
/* **/
|
||||
/* * Written by: Glenn Engel $*/
|
||||
/* * ModuleState: Experimental $*/
|
||||
/* **/
|
||||
/* * NOTES: See Below $*/
|
||||
/* **/
|
||||
/* * Modified for 386 by Jim Kingdon, Cygnus Support.*/
|
||||
/* **/
|
||||
/* * To enable debugger support, two things need to happen. One, a*/
|
||||
/* * call to set_debug_traps() is necessary in order to allow any breakpoints*/
|
||||
/* * or error conditions to be properly intercepted and reported to gdb.*/
|
||||
/* * Two, a breakpoint needs to be generated to begin communication. This*/
|
||||
/* * is most easily accomplished by a call to breakpoint(). Breakpoint()*/
|
||||
/* * simulates a breakpoint by executing a trap #1.*/
|
||||
/* **/
|
||||
/* * The external function exceptionHandler() is*/
|
||||
/* * used to attach a specific handler to a specific 386 vector number.*/
|
||||
/* * It should use the same privilege level it runs at. It should*/
|
||||
/* * install it as an interrupt gate so that interrupts are masked*/
|
||||
/* * while the handler runs.*/
|
||||
/* **/
|
||||
/* * Because gdb will sometimes write to the stack area to execute function*/
|
||||
/* * calls, this program cannot rely on using the supervisor stack so it*/
|
||||
/* * uses it's own stack area reserved in the int array remcomStack.*/
|
||||
/* **/
|
||||
/* **************/
|
||||
/* **/
|
||||
/* * The following gdb commands are supported:*/
|
||||
/* **/
|
||||
/* * command function Return value*/
|
||||
/* **/
|
||||
/* * g return the value of the CPU registers hex data or ENN*/
|
||||
/* * G set the value of the CPU registers OK or ENN*/
|
||||
/* **/
|
||||
/* * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN*/
|
||||
/* * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN*/
|
||||
/* **/
|
||||
/* * c Resume at current address SNN ( signal NN)*/
|
||||
/* * cAA..AA Continue at address AA..AA SNN*/
|
||||
/* **/
|
||||
/* * s Step one instruction SNN*/
|
||||
/* * sAA..AA Step one instruction from AA..AA SNN*/
|
||||
/* **/
|
||||
/* * k kill*/
|
||||
/* **/
|
||||
/* * ? What was the last sigval ? SNN (signal NN)*/
|
||||
/* **/
|
||||
/* * All commands and responses are sent with a packet which includes a*/
|
||||
/* * checksum. A packet consists of*/
|
||||
/* **/
|
||||
/* * $<packet info>#<checksum>.*/
|
||||
/* **/
|
||||
/* * where*/
|
||||
/* * <packet info> :: <characters representing the command or response>*/
|
||||
/* * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>*/
|
||||
/* **/
|
||||
/* * When a packet is received, it is first acknowledged with either '+' or '-'.*/
|
||||
/* * '+' indicates a successful transfer. '-' indicates a failed transfer.*/
|
||||
/* **/
|
||||
/* * Example:*/
|
||||
/* **/
|
||||
/* * Host: Reply:*/
|
||||
/* * $m0,10#2a +$00010203040506070809101112131415#42*/
|
||||
/* **/
|
||||
/* ****************************************************************************/*/
|
||||
|
||||
/*#include <stdio.h>*/
|
||||
/*#include <string.h>*/
|
||||
|
||||
/*/*************************************************************************/
|
||||
/* **/
|
||||
/* * external low-level support routines*/
|
||||
/* */*/
|
||||
|
||||
/*extern void putDebugChar(); /* write a single character */*/
|
||||
/*extern int getDebugChar(); /* read and return a single char */*/
|
||||
/*extern void exceptionHandler(); /* assign an exception handler */*/
|
||||
|
||||
/*/************************************************************************/*/
|
||||
/*/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/*/
|
||||
/*/* at least NUMREGBYTES*2 are needed for register packets */*/
|
||||
/*#define BUFMAX 400*/
|
||||
|
||||
/*static char initialized; /* boolean flag. != 0 means we've been initialized */*/
|
||||
|
||||
/*int remote_debug = 1;*/
|
||||
/*/* debug > 0 prints ill-formed commands in valid packets & checksum errors */*/
|
||||
|
||||
/*static const char hexchars[]="0123456789abcdef";*/
|
||||
|
||||
/*/* Number of registers. */*/
|
||||
/*#define NUMREGS 16*/
|
||||
|
||||
/*/* Number of bytes of registers. */*/
|
||||
/*#define NUMREGBYTES (NUMREGS * 4)*/
|
||||
|
||||
/*enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,*/
|
||||
/* PC /* also known as eip */,*/
|
||||
/* PS /* also known as eflags */,*/
|
||||
/* CS, SS, DS, ES, FS, GS};*/
|
||||
|
||||
/*/**/
|
||||
/* * these should not be static cuz they can be used outside this module*/
|
||||
/* */*/
|
||||
/*int registers[NUMREGS];*/
|
||||
|
||||
/*#define STACKSIZE 10000*/
|
||||
/*int remcomStack[STACKSIZE/sizeof(int)];*/
|
||||
/*static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];*/
|
||||
|
||||
/*/*************************** ASSEMBLY CODE MACROS *************************/*/
|
||||
/*/* */*/
|
||||
|
||||
/*extern void*/
|
||||
/*return_to_prog ();*/
|
||||
|
||||
/*/* Restore the program's registers (including the stack pointer, which*/
|
||||
/* means we get the right stack and don't have to worry about popping our*/
|
||||
/* return address and any stack frames and so on) and return. */*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl return_to_prog");*/
|
||||
/*asm("return_to_prog:");*/
|
||||
/*asm(" movw registers+44, %ss");*/
|
||||
/*asm(" movl registers+16, %esp");*/
|
||||
/*asm(" movl registers+4, %ecx");*/
|
||||
/*asm(" movl registers+8, %edx");*/
|
||||
/*asm(" movl registers+12, %ebx");*/
|
||||
/*asm(" movl registers+20, %ebp");*/
|
||||
/*asm(" movl registers+24, %esi");*/
|
||||
/*asm(" movl registers+28, %edi");*/
|
||||
/*asm(" movw registers+48, %ds");*/
|
||||
/*asm(" movw registers+52, %es");*/
|
||||
/*asm(" movw registers+56, %fs");*/
|
||||
/*asm(" movw registers+60, %gs");*/
|
||||
/*asm(" movl registers+36, %eax");*/
|
||||
/*asm(" pushl %eax"); /* saved eflags */*/
|
||||
/*asm(" movl registers+40, %eax");*/
|
||||
/*asm(" pushl %eax"); /* saved cs */*/
|
||||
/*asm(" movl registers+32, %eax");*/
|
||||
/*asm(" pushl %eax"); /* saved eip */*/
|
||||
/*asm(" movl registers, %eax");*/
|
||||
/*/* use iret to restore pc and flags together so*/
|
||||
/* that trace flag works right. */*/
|
||||
/*asm(" iret");*/
|
||||
|
||||
/*#define BREAKPOINT() asm(" int $3");*/
|
||||
|
||||
/*/* Put the error code here just in case the user cares. */*/
|
||||
/*int gdb_i386errcode;*/
|
||||
/*/* Likewise, the vector number here (since GDB only gets the signal*/
|
||||
/* number through the usual means, and that's not very specific). */*/
|
||||
/*int gdb_i386vector = -1;*/
|
||||
|
||||
/*/* GDB stores segment registers in 32-bit words (that's just the way*/
|
||||
/* m-i386v.h is written). So zero the appropriate areas in registers. */*/
|
||||
/*#define SAVE_REGISTERS1() \*/
|
||||
/* asm ("movl %eax, registers"); \*/
|
||||
/* asm ("movl %ecx, registers+4"); \*/
|
||||
/* asm ("movl %edx, registers+8"); \*/
|
||||
/* asm ("movl %ebx, registers+12"); \*/
|
||||
/* asm ("movl %ebp, registers+20"); \*/
|
||||
/* asm ("movl %esi, registers+24"); \*/
|
||||
/* asm ("movl %edi, registers+28"); \*/
|
||||
/* asm ("movw $0, %ax"); \*/
|
||||
/* asm ("movw %ds, registers+48"); \*/
|
||||
/* asm ("movw %ax, registers+50"); \*/
|
||||
/* asm ("movw %es, registers+52"); \*/
|
||||
/* asm ("movw %ax, registers+54"); \*/
|
||||
/* asm ("movw %fs, registers+56"); \*/
|
||||
/* asm ("movw %ax, registers+58"); \*/
|
||||
/* asm ("movw %gs, registers+60"); \*/
|
||||
/* asm ("movw %ax, registers+62");*/
|
||||
/*#define SAVE_ERRCODE() \*/
|
||||
/* asm ("popl %ebx"); \*/
|
||||
/* asm ("movl %ebx, gdb_i386errcode");*/
|
||||
/*#define SAVE_REGISTERS2() \*/
|
||||
/* asm ("popl %ebx"); /* old eip */ \*/
|
||||
/* asm ("movl %ebx, registers+32"); \*/
|
||||
/* asm ("popl %ebx"); /* old cs */ \*/
|
||||
/* asm ("movl %ebx, registers+40"); \*/
|
||||
/* asm ("movw %ax, registers+42"); \*/
|
||||
/* asm ("popl %ebx"); /* old eflags */ \*/
|
||||
/* asm ("movl %ebx, registers+36"); \*/
|
||||
/* /* Now that we've done the pops, we can save the stack pointer."); */ \*/
|
||||
/* asm ("movw %ss, registers+44"); \*/
|
||||
/* asm ("movw %ax, registers+46"); \*/
|
||||
/* asm ("movl %esp, registers+16");*/
|
||||
|
||||
/*/* See if mem_fault_routine is set, if so just IRET to that address. */*/
|
||||
/*#define CHECK_FAULT() \*/
|
||||
/* asm ("cmpl $0, mem_fault_routine"); \*/
|
||||
/* asm ("jne mem_fault");*/
|
||||
|
||||
/*asm (".text");*/
|
||||
/*asm ("mem_fault:");*/
|
||||
/*/* OK to clobber temp registers; we're just going to end up in set_mem_err. */*/
|
||||
/*/* Pop error code from the stack and save it. */*/
|
||||
/*asm (" popl %eax");*/
|
||||
/*asm (" movl %eax, gdb_i386errcode");*/
|
||||
|
||||
/*asm (" popl %eax"); /* eip */*/
|
||||
/*/* We don't want to return there, we want to return to the function*/
|
||||
/* pointed to by mem_fault_routine instead. */*/
|
||||
/*asm (" movl mem_fault_routine, %eax");*/
|
||||
/*asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */*/
|
||||
/*asm (" popl %edx"); /* eflags */*/
|
||||
|
||||
/*/* Remove this stack frame; when we do the iret, we will be going to*/
|
||||
/* the start of a function, so we want the stack to look just like it*/
|
||||
/* would after a "call" instruction. */*/
|
||||
/*asm (" leave");*/
|
||||
|
||||
/*/* Push the stuff that iret wants. */*/
|
||||
/*asm (" pushl %edx"); /* eflags */*/
|
||||
/*asm (" pushl %ecx"); /* cs */*/
|
||||
/*asm (" pushl %eax"); /* eip */*/
|
||||
|
||||
/*/* Zero mem_fault_routine. */*/
|
||||
/*asm (" movl $0, %eax");*/
|
||||
/*asm (" movl %eax, mem_fault_routine");*/
|
||||
|
||||
/*asm ("iret");*/
|
||||
|
||||
/*#define CALL_HOOK() asm("call remcomHandler");*/
|
||||
|
||||
/*/* This function is called when a i386 exception occurs. It saves*/
|
||||
/* * all the cpu regs in the _registers array, munges the stack a bit,*/
|
||||
/* * and invokes an exception handler (remcom_handler).*/
|
||||
/* **/
|
||||
/* * stack on entry: stack on exit:*/
|
||||
/* * old eflags vector number*/
|
||||
/* * old cs (zero-filled to 32 bits)*/
|
||||
/* * old eip*/
|
||||
/* **/
|
||||
/* */*/
|
||||
/*extern void catchException3();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException3");*/
|
||||
/*asm("catchException3:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $3");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 1. */*/
|
||||
/*extern void catchException1();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException1");*/
|
||||
/*asm("catchException1:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $1");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 0. */*/
|
||||
/*extern void catchException0();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException0");*/
|
||||
/*asm("catchException0:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $0");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 4. */*/
|
||||
/*extern void catchException4();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException4");*/
|
||||
/*asm("catchException4:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $4");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 5. */*/
|
||||
/*extern void catchException5();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException5");*/
|
||||
/*asm("catchException5:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $5");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 6. */*/
|
||||
/*extern void catchException6();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException6");*/
|
||||
/*asm("catchException6:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $6");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 7. */*/
|
||||
/*extern void catchException7();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException7");*/
|
||||
/*asm("catchException7:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $7");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 8. */*/
|
||||
/*extern void catchException8();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException8");*/
|
||||
/*asm("catchException8:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $8");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 9. */*/
|
||||
/*extern void catchException9();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException9");*/
|
||||
/*asm("catchException9:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $9");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 10. */*/
|
||||
/*extern void catchException10();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException10");*/
|
||||
/*asm("catchException10:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $10");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 12. */*/
|
||||
/*extern void catchException12();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException12");*/
|
||||
/*asm("catchException12:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $12");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 16. */*/
|
||||
/*extern void catchException16();*/
|
||||
/*asm(".text");*/
|
||||
/*asm(".globl catchException16");*/
|
||||
/*asm("catchException16:");*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $16");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */*/
|
||||
|
||||
/*/* Same thing for exception 13. */*/
|
||||
/*extern void catchException13 ();*/
|
||||
/*asm (".text");*/
|
||||
/*asm (".globl catchException13");*/
|
||||
/*asm ("catchException13:");*/
|
||||
/*CHECK_FAULT();*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $13");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 11. */*/
|
||||
/*extern void catchException11 ();*/
|
||||
/*asm (".text");*/
|
||||
/*asm (".globl catchException11");*/
|
||||
/*asm ("catchException11:");*/
|
||||
/*CHECK_FAULT();*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $11");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/* Same thing for exception 14. */*/
|
||||
/*extern void catchException14 ();*/
|
||||
/*asm (".text");*/
|
||||
/*asm (".globl catchException14");*/
|
||||
/*asm ("catchException14:");*/
|
||||
/*CHECK_FAULT();*/
|
||||
/*SAVE_REGISTERS1();*/
|
||||
/*SAVE_ERRCODE();*/
|
||||
/*SAVE_REGISTERS2();*/
|
||||
/*asm ("pushl $14");*/
|
||||
/*CALL_HOOK();*/
|
||||
|
||||
/*/**/
|
||||
/* * remcomHandler is a front end for handle_exception. It moves the*/
|
||||
/* * stack pointer into an area reserved for debugger use.*/
|
||||
/* */*/
|
||||
/*asm("remcomHandler:");*/
|
||||
/*asm(" popl %eax"); /* pop off return address */*/
|
||||
/*asm(" popl %eax"); /* get the exception number */*/
|
||||
/*asm(" movl stackPtr, %esp"); /* move to remcom stack area */*/
|
||||
/*asm(" pushl %eax"); /* push exception onto stack */*/
|
||||
/*asm(" call handle_exception"); /* this never returns */*/
|
||||
|
||||
/*void*/
|
||||
/*returnFromException ()*/
|
||||
/*{*/
|
||||
/* return_to_prog ();*/
|
||||
/*}*/
|
||||
|
||||
/*int*/
|
||||
/*hex (ch)*/
|
||||
/* char ch;*/
|
||||
/*{*/
|
||||
/* if ((ch >= 'a') && (ch <= 'f'))*/
|
||||
/* return (ch - 'a' + 10);*/
|
||||
/* if ((ch >= '0') && (ch <= '9'))*/
|
||||
/* return (ch - '0');*/
|
||||
/* if ((ch >= 'A') && (ch <= 'F'))*/
|
||||
/* return (ch - 'A' + 10);*/
|
||||
/* return (-1);*/
|
||||
/*}*/
|
||||
|
||||
/*static char remcomInBuffer[BUFMAX];*/
|
||||
/*static char remcomOutBuffer[BUFMAX];*/
|
||||
|
||||
/*/* scan for the sequence $<data>#<checksum> */*/
|
||||
|
||||
/*unsigned char **/
|
||||
/*getpacket (void)*/
|
||||
/*{*/
|
||||
/* serial_print("GETPACKET\n");*/
|
||||
/* unsigned char *buffer = &remcomInBuffer[0];*/
|
||||
/* unsigned char checksum;*/
|
||||
/* unsigned char xmitcsum;*/
|
||||
/* int count;*/
|
||||
/* char ch;*/
|
||||
|
||||
/* while (1)*/
|
||||
/* {*/
|
||||
/* serial_print("IN OUTER LOOP\n");*/
|
||||
/* /* wait around for the start character, ignore all other characters */*/
|
||||
/* while ((ch = getDebugChar ()) != '$')*/
|
||||
/* serial_print("GOT NON $ byte\n");*/
|
||||
|
||||
/* retry:*/
|
||||
/* serial_print("PACKET READ STARTED\n");*/
|
||||
/* checksum = 0;*/
|
||||
/* xmitcsum = -1;*/
|
||||
/* count = 0;*/
|
||||
|
||||
/* /* now, read until a # or end of buffer is found */*/
|
||||
/* while (count < BUFMAX - 1)*/
|
||||
/* {*/
|
||||
/* ch = getDebugChar ();*/
|
||||
/* if (ch == '$')*/
|
||||
/* goto retry;*/
|
||||
/* if (ch == '#')*/
|
||||
/* break;*/
|
||||
/* checksum = checksum + ch;*/
|
||||
/* buffer[count] = ch;*/
|
||||
/* count = count + 1;*/
|
||||
/* }*/
|
||||
/* buffer[count] = 0;*/
|
||||
|
||||
/* if (ch == '#')*/
|
||||
/* {*/
|
||||
/* ch = getDebugChar ();*/
|
||||
/* xmitcsum = hex (ch) << 4;*/
|
||||
/* ch = getDebugChar ();*/
|
||||
/* xmitcsum += hex (ch);*/
|
||||
|
||||
/* /* if (checksum != xmitcsum) */*/
|
||||
/* /* { */*/
|
||||
/* /* if (remote_debug) */*/
|
||||
/* /* { */*/
|
||||
/* /* fprintf (stderr, */*/
|
||||
/* /* "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", */*/
|
||||
/* /* checksum, xmitcsum, buffer); */*/
|
||||
/* /* } */*/
|
||||
/* /* putDebugChar ('-'); /1* failed checksum *1/ */*/
|
||||
/* /* } */*/
|
||||
/* /* else */*/
|
||||
/* /* { */*/
|
||||
/* putDebugChar ('+'); /* successful transfer */*/
|
||||
|
||||
/* /* if a sequence char is present, reply the sequence ID */*/
|
||||
/* if (buffer[2] == ':')*/
|
||||
/* {*/
|
||||
/* putDebugChar (buffer[0]);*/
|
||||
/* putDebugChar (buffer[1]);*/
|
||||
|
||||
/* return &buffer[3];*/
|
||||
/* }*/
|
||||
|
||||
/* return &buffer[0];*/
|
||||
/* /* } */*/
|
||||
/* }*/
|
||||
/* }*/
|
||||
/*}*/
|
||||
|
||||
/*/* send the packet in buffer. */*/
|
||||
|
||||
/*void*/
|
||||
/*putpacket (unsigned char *buffer)*/
|
||||
/*{*/
|
||||
/* unsigned char checksum;*/
|
||||
/* int count;*/
|
||||
/* char ch;*/
|
||||
|
||||
/* /* $<packet info>#<checksum>. */*/
|
||||
/* do*/
|
||||
/* {*/
|
||||
/* putDebugChar ('$');*/
|
||||
/* checksum = 0;*/
|
||||
/* count = 0;*/
|
||||
|
||||
/* while (ch = buffer[count])*/
|
||||
/* {*/
|
||||
/* putDebugChar (ch);*/
|
||||
/* checksum += ch;*/
|
||||
/* count += 1;*/
|
||||
/* }*/
|
||||
|
||||
/* putDebugChar ('#');*/
|
||||
/* putDebugChar (hexchars[checksum >> 4]);*/
|
||||
/* putDebugChar (hexchars[checksum % 16]);*/
|
||||
|
||||
/* }*/
|
||||
/* while (getDebugChar () != '+');*/
|
||||
/*}*/
|
||||
|
||||
/*void*/
|
||||
/*debug_error (format, parm)*/
|
||||
/* char *format;*/
|
||||
/* char *parm;*/
|
||||
/*{*/
|
||||
/* if (remote_debug)*/
|
||||
/* fprintf (stderr, format, parm);*/
|
||||
/*}*/
|
||||
|
||||
/*/* Address of a routine to RTE to if we get a memory fault. */*/
|
||||
/*static void (*volatile mem_fault_routine) () = NULL;*/
|
||||
|
||||
/*/* Indicate to caller of mem2hex or hex2mem that there has been an*/
|
||||
/* error. */*/
|
||||
/*static volatile int mem_err = 0;*/
|
||||
|
||||
/*void*/
|
||||
/*set_mem_err (void)*/
|
||||
/*{*/
|
||||
/* mem_err = 1;*/
|
||||
/*}*/
|
||||
|
||||
/*/* These are separate functions so that they are so short and sweet*/
|
||||
/* that the compiler won't save any registers (if there is a fault*/
|
||||
/* to mem_fault, they won't get restored, so there better not be any*/
|
||||
/* saved). */*/
|
||||
/*int*/
|
||||
/*get_char (char *addr)*/
|
||||
/*{*/
|
||||
/* return *addr;*/
|
||||
/*}*/
|
||||
|
||||
/*void*/
|
||||
/*set_char (char *addr, int val)*/
|
||||
/*{*/
|
||||
/* *addr = val;*/
|
||||
/*}*/
|
||||
|
||||
/*/* convert the memory pointed to by mem into hex, placing result in buf */*/
|
||||
/*/* return a pointer to the last char put in buf (null) */*/
|
||||
/*/* If MAY_FAULT is non-zero, then we should set mem_err in response to*/
|
||||
/* a fault; if zero treat a fault like any other fault in the stub. */*/
|
||||
/*char **/
|
||||
/*mem2hex (mem, buf, count, may_fault)*/
|
||||
/* char *mem;*/
|
||||
/* char *buf;*/
|
||||
/* int count;*/
|
||||
/* int may_fault;*/
|
||||
/*{*/
|
||||
/* int i;*/
|
||||
/* unsigned char ch;*/
|
||||
|
||||
/* if (may_fault)*/
|
||||
/* mem_fault_routine = set_mem_err;*/
|
||||
/* for (i = 0; i < count; i++)*/
|
||||
/* {*/
|
||||
/* ch = get_char (mem++);*/
|
||||
/* if (may_fault && mem_err)*/
|
||||
/* return (buf);*/
|
||||
/* *buf++ = hexchars[ch >> 4];*/
|
||||
/* *buf++ = hexchars[ch % 16];*/
|
||||
/* }*/
|
||||
/* *buf = 0;*/
|
||||
/* if (may_fault)*/
|
||||
/* mem_fault_routine = NULL;*/
|
||||
/* return (buf);*/
|
||||
/*}*/
|
||||
|
||||
/*/* convert the hex array pointed to by buf into binary to be placed in mem */*/
|
||||
/*/* return a pointer to the character AFTER the last byte written */*/
|
||||
/*char **/
|
||||
/*hex2mem (buf, mem, count, may_fault)*/
|
||||
/* char *buf;*/
|
||||
/* char *mem;*/
|
||||
/* int count;*/
|
||||
/* int may_fault;*/
|
||||
/*{*/
|
||||
/* int i;*/
|
||||
/* unsigned char ch;*/
|
||||
|
||||
/* if (may_fault)*/
|
||||
/* mem_fault_routine = set_mem_err;*/
|
||||
/* for (i = 0; i < count; i++)*/
|
||||
/* {*/
|
||||
/* ch = hex (*buf++) << 4;*/
|
||||
/* ch = ch + hex (*buf++);*/
|
||||
/* set_char (mem++, ch);*/
|
||||
/* if (may_fault && mem_err)*/
|
||||
/* return (mem);*/
|
||||
/* }*/
|
||||
/* if (may_fault)*/
|
||||
/* mem_fault_routine = NULL;*/
|
||||
/* return (mem);*/
|
||||
/*}*/
|
||||
|
||||
/*/* this function takes the 386 exception vector and attempts to*/
|
||||
/* translate this number into a unix compatible signal value */*/
|
||||
/*int*/
|
||||
/*computeSignal (int exceptionVector)*/
|
||||
/*{*/
|
||||
/* int sigval;*/
|
||||
/* switch (exceptionVector)*/
|
||||
/* {*/
|
||||
/* case 0:*/
|
||||
/* sigval = 8;*/
|
||||
/* break; /* divide by zero */*/
|
||||
/* case 1:*/
|
||||
/* sigval = 5;*/
|
||||
/* break; /* debug exception */*/
|
||||
/* case 3:*/
|
||||
/* sigval = 5;*/
|
||||
/* break; /* breakpoint */*/
|
||||
/* case 4:*/
|
||||
/* sigval = 16;*/
|
||||
/* break; /* into instruction (overflow) */*/
|
||||
/* case 5:*/
|
||||
/* sigval = 16;*/
|
||||
/* break; /* bound instruction */*/
|
||||
/* case 6:*/
|
||||
/* sigval = 4;*/
|
||||
/* break; /* Invalid opcode */*/
|
||||
/* case 7:*/
|
||||
/* sigval = 8;*/
|
||||
/* break; /* coprocessor not available */*/
|
||||
/* case 8:*/
|
||||
/* sigval = 7;*/
|
||||
/* break; /* double fault */*/
|
||||
/* case 9:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* coprocessor segment overrun */*/
|
||||
/* case 10:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* Invalid TSS */*/
|
||||
/* case 11:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* Segment not present */*/
|
||||
/* case 12:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* stack exception */*/
|
||||
/* case 13:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* general protection */*/
|
||||
/* case 14:*/
|
||||
/* sigval = 11;*/
|
||||
/* break; /* page fault */*/
|
||||
/* case 16:*/
|
||||
/* sigval = 7;*/
|
||||
/* break; /* coprocessor error */*/
|
||||
/* default:*/
|
||||
/* sigval = 7; /* "software generated" */*/
|
||||
/* }*/
|
||||
/* return (sigval);*/
|
||||
/*}*/
|
||||
|
||||
/*/**********************************************/*/
|
||||
/*/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */*/
|
||||
/*/* RETURN NUMBER OF CHARS PROCESSED */*/
|
||||
/*/**********************************************/*/
|
||||
/*int*/
|
||||
/*hexToInt (char **ptr, int *intValue)*/
|
||||
/*{*/
|
||||
/* int numChars = 0;*/
|
||||
/* int hexValue;*/
|
||||
|
||||
/* *intValue = 0;*/
|
||||
|
||||
/* while (**ptr)*/
|
||||
/* {*/
|
||||
/* hexValue = hex (**ptr);*/
|
||||
/* if (hexValue >= 0)*/
|
||||
/* {*/
|
||||
/* *intValue = (*intValue << 4) | hexValue;*/
|
||||
/* numChars++;*/
|
||||
/* }*/
|
||||
/* else*/
|
||||
/* break;*/
|
||||
|
||||
/* (*ptr)++;*/
|
||||
/* }*/
|
||||
|
||||
/* return (numChars);*/
|
||||
/*}*/
|
||||
|
||||
/*/**/
|
||||
/* * This function does all command procesing for interfacing to gdb.*/
|
||||
/* */*/
|
||||
/*void*/
|
||||
/*handle_exception (int exceptionVector)*/
|
||||
/*{*/
|
||||
/* serial_print("GDB EXCEPTION HANDLER\n");*/
|
||||
/* int sigval, stepping;*/
|
||||
/* int addr, length;*/
|
||||
/* char *ptr;*/
|
||||
/* int newPC;*/
|
||||
|
||||
/* gdb_i386vector = exceptionVector;*/
|
||||
|
||||
/* if (remote_debug)*/
|
||||
/* {*/
|
||||
/* printf ("vector=%d, sr=0x%x, pc=0x%x\n",*/
|
||||
/* exceptionVector, registers[PS], registers[PC]);*/
|
||||
/* }*/
|
||||
|
||||
/* /* reply to host that an exception has occurred */*/
|
||||
/* sigval = computeSignal (exceptionVector);*/
|
||||
|
||||
/* ptr = remcomOutBuffer;*/
|
||||
|
||||
/* *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */*/
|
||||
/* *ptr++ = hexchars[sigval >> 4];*/
|
||||
/* *ptr++ = hexchars[sigval & 0xf];*/
|
||||
|
||||
/* *ptr++ = hexchars[ESP];*/
|
||||
/* *ptr++ = ':';*/
|
||||
/* ptr = mem2hex((char *)®isters[ESP], ptr, 4, 0); /* SP */*/
|
||||
/* *ptr++ = ';';*/
|
||||
|
||||
/* *ptr++ = hexchars[EBP];*/
|
||||
/* *ptr++ = ':';*/
|
||||
/* ptr = mem2hex((char *)®isters[EBP], ptr, 4, 0); /* FP */*/
|
||||
/* *ptr++ = ';';*/
|
||||
|
||||
/* *ptr++ = hexchars[PC];*/
|
||||
/* *ptr++ = ':';*/
|
||||
/* ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); /* PC */*/
|
||||
/* *ptr++ = ';';*/
|
||||
|
||||
/* *ptr = '\0';*/
|
||||
|
||||
/* putpacket (remcomOutBuffer);*/
|
||||
|
||||
/* stepping = 0;*/
|
||||
|
||||
/* while (1 == 1)*/
|
||||
/* {*/
|
||||
/* remcomOutBuffer[0] = 0;*/
|
||||
/* ptr = getpacket ();*/
|
||||
|
||||
/* switch (*ptr++)*/
|
||||
/* {*/
|
||||
/* case '?':*/
|
||||
/* remcomOutBuffer[0] = 'S';*/
|
||||
/* remcomOutBuffer[1] = hexchars[sigval >> 4];*/
|
||||
/* remcomOutBuffer[2] = hexchars[sigval % 16];*/
|
||||
/* remcomOutBuffer[3] = 0;*/
|
||||
/* break;*/
|
||||
/* case 'd':*/
|
||||
/* remote_debug = !(remote_debug); /* toggle debug flag */*/
|
||||
/* break;*/
|
||||
/* case 'g': /* return the value of the CPU registers */*/
|
||||
/* mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);*/
|
||||
/* break;*/
|
||||
/* case 'G': /* set the value of the CPU registers - return OK */*/
|
||||
/* hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);*/
|
||||
/* strcpy (remcomOutBuffer, "OK");*/
|
||||
/* break;*/
|
||||
/* case 'P': /* set the value of a single CPU register - return OK */*/
|
||||
/* {*/
|
||||
/* int regno;*/
|
||||
|
||||
/* if (hexToInt (&ptr, ®no) && *ptr++ == '=')*/
|
||||
/* if (regno >= 0 && regno < NUMREGS)*/
|
||||
/* {*/
|
||||
/* hex2mem (ptr, (char *) ®isters[regno], 4, 0);*/
|
||||
/* strcpy (remcomOutBuffer, "OK");*/
|
||||
/* break;*/
|
||||
/* }*/
|
||||
|
||||
/* strcpy (remcomOutBuffer, "E01");*/
|
||||
/* break;*/
|
||||
/* }*/
|
||||
|
||||
/* /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */*/
|
||||
/* case 'm':*/
|
||||
/* /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */*/
|
||||
/* if (hexToInt (&ptr, &addr))*/
|
||||
/* if (*(ptr++) == ',')*/
|
||||
/* if (hexToInt (&ptr, &length))*/
|
||||
/* {*/
|
||||
/* ptr = 0;*/
|
||||
/* mem_err = 0;*/
|
||||
/* mem2hex ((char *) addr, remcomOutBuffer, length, 1);*/
|
||||
/* if (mem_err)*/
|
||||
/* {*/
|
||||
/* strcpy (remcomOutBuffer, "E03");*/
|
||||
/* debug_error ("memory fault");*/
|
||||
/* }*/
|
||||
/* }*/
|
||||
|
||||
/* if (ptr)*/
|
||||
/* {*/
|
||||
/* strcpy (remcomOutBuffer, "E01");*/
|
||||
/* }*/
|
||||
/* break;*/
|
||||
|
||||
/* /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */*/
|
||||
/* case 'M':*/
|
||||
/* /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */*/
|
||||
/* if (hexToInt (&ptr, &addr))*/
|
||||
/* if (*(ptr++) == ',')*/
|
||||
/* if (hexToInt (&ptr, &length))*/
|
||||
/* if (*(ptr++) == ':')*/
|
||||
/* {*/
|
||||
/* mem_err = 0;*/
|
||||
/* hex2mem (ptr, (char *) addr, length, 1);*/
|
||||
|
||||
/* if (mem_err)*/
|
||||
/* {*/
|
||||
/* strcpy (remcomOutBuffer, "E03");*/
|
||||
/* debug_error ("memory fault");*/
|
||||
/* }*/
|
||||
/* else*/
|
||||
/* {*/
|
||||
/* strcpy (remcomOutBuffer, "OK");*/
|
||||
/* }*/
|
||||
|
||||
/* ptr = 0;*/
|
||||
/* }*/
|
||||
/* if (ptr)*/
|
||||
/* {*/
|
||||
/* strcpy (remcomOutBuffer, "E02");*/
|
||||
/* }*/
|
||||
/* break;*/
|
||||
|
||||
/* /* cAA..AA Continue at address AA..AA(optional) */*/
|
||||
/* /* sAA..AA Step one instruction from AA..AA(optional) */*/
|
||||
/* case 's':*/
|
||||
/* stepping = 1;*/
|
||||
/* case 'c':*/
|
||||
/* /* try to read optional parameter, pc unchanged if no parm */*/
|
||||
/* if (hexToInt (&ptr, &addr))*/
|
||||
/* registers[PC] = addr;*/
|
||||
|
||||
/* newPC = registers[PC];*/
|
||||
|
||||
/* /* clear the trace bit */*/
|
||||
/* registers[PS] &= 0xfffffeff;*/
|
||||
|
||||
/* /* set the trace bit if we're stepping */*/
|
||||
/* if (stepping)*/
|
||||
/* registers[PS] |= 0x100;*/
|
||||
|
||||
/* returnFromException (); /* this is a jump */*/
|
||||
/* break;*/
|
||||
|
||||
/* /* kill the program */*/
|
||||
/* case 'k': /* do nothing */*/
|
||||
/*#if 0*/
|
||||
/* /* Huh? This doesn't look like "nothing".*/
|
||||
/* m68k-stub.c and sparc-stub.c don't have it. */*/
|
||||
/* BREAKPOINT ();*/
|
||||
/*#endif*/
|
||||
/* break;*/
|
||||
/* } /* switch */*/
|
||||
|
||||
/* /* reply to the request */*/
|
||||
/* putpacket (remcomOutBuffer);*/
|
||||
/* }*/
|
||||
/*}*/
|
||||
|
||||
/*/* this function is used to set up exception handlers for tracing and*/
|
||||
/* breakpoints */*/
|
||||
/*void*/
|
||||
/*set_debug_traps (void)*/
|
||||
/*{*/
|
||||
/* stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];*/
|
||||
|
||||
/* exceptionHandler (0, catchException0);*/
|
||||
/* exceptionHandler (1, catchException1);*/
|
||||
/* exceptionHandler (3, catchException3);*/
|
||||
/* exceptionHandler (4, catchException4);*/
|
||||
/* exceptionHandler (5, catchException5);*/
|
||||
/* exceptionHandler (6, catchException6);*/
|
||||
/* exceptionHandler (7, catchException7);*/
|
||||
/* exceptionHandler (8, catchException8);*/
|
||||
/* exceptionHandler (9, catchException9);*/
|
||||
/* exceptionHandler (10, catchException10);*/
|
||||
/* exceptionHandler (11, catchException11);*/
|
||||
/* exceptionHandler (12, catchException12);*/
|
||||
/* exceptionHandler (13, catchException13);*/
|
||||
/* exceptionHandler (14, catchException14);*/
|
||||
/* exceptionHandler (16, catchException16);*/
|
||||
|
||||
/* initialized = 1;*/
|
||||
/*}*/
|
||||
|
||||
/*/* This function will generate a breakpoint exception. It is used at the*/
|
||||
/* beginning of a program to sync up with a debugger and can be used*/
|
||||
/* otherwise as a quick means to stop program execution and "break" into*/
|
||||
/* the debugger. */*/
|
||||
|
||||
/*void*/
|
||||
/*breakpoint (void)*/
|
||||
/*{*/
|
||||
/* if (initialized)*/
|
||||
/* BREAKPOINT ();*/
|
||||
/*}*/
|
68
init/main.c
68
init/main.c
@ -22,6 +22,30 @@ typedef struct {
|
||||
char typeflag[1];
|
||||
} tar_header;
|
||||
|
||||
extern int registers[16];
|
||||
|
||||
/**
|
||||
* Saved state of the CPU when an interrupt occurs
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t ds; //!< Data segment selector
|
||||
uint32_t edi; //!< Pushed by pusha.
|
||||
uint32_t esi; //!< Pushed by pusha.
|
||||
uint32_t ebp; //!< Pushed by pusha.
|
||||
uint32_t esp; //!< Pushed by pusha.
|
||||
uint32_t ebx; //!< Pushed by pusha.
|
||||
uint32_t edx; //!< Pushed by pusha.
|
||||
uint32_t ecx; //!< Pushed by pusha.
|
||||
uint32_t eax; //!< Pushed by pusha.
|
||||
uint32_t int_no; //!< Interrupt number
|
||||
uint32_t err_code; //!< Error code (if applicable)
|
||||
uint32_t eip; //!< Pushed by the processor automatically
|
||||
uint32_t cs; //!< Pushed by the processor automatically
|
||||
uint32_t eflags; //!< Pushed by the processor automatically
|
||||
uint32_t useresp; //!< Pushed by the processor automatically
|
||||
uint32_t ss; //!< Pushed by the processor automatically
|
||||
} registers_t;
|
||||
|
||||
size_t getsize(const char *in) {
|
||||
size_t size=0;
|
||||
size_t j;
|
||||
@ -92,8 +116,50 @@ char load_proc(size_t datapos,char* initrd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char getDebugChar() {
|
||||
return user_serial_getc(1);
|
||||
}
|
||||
|
||||
void putDebugChar(char c) {
|
||||
user_serial_putc(c, 1);
|
||||
}
|
||||
|
||||
void exceptionHandler(int exception_number, void *exception_address) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* void user_handler(registers_t* r) { */
|
||||
/* serial_print("USER EXCEPTION HANDLER\n"); */
|
||||
/* registers[0]=r->eax; */
|
||||
/* registers[1]=r->ecx; */
|
||||
/* registers[2]=r->edx; */
|
||||
/* registers[3]=r->ebx; */
|
||||
/* registers[4]=r->esp; */
|
||||
/* registers[5]=r->ebp; */
|
||||
/* registers[6]=r->esi; */
|
||||
/* registers[7]=r->edi; */
|
||||
/* registers[8]=r->eip; */
|
||||
/* registers[9]=r->eflags; */
|
||||
/* registers[10]=0x8; */
|
||||
/* registers[11]=0x10; */
|
||||
/* registers[12]=0x10; */
|
||||
/* registers[13]=0x10; */
|
||||
/* registers[14]=0x10; */
|
||||
/* registers[15]=0x10; */
|
||||
/* handle_exception(r->int_no); */
|
||||
/* exception_return(); */
|
||||
/* } */
|
||||
|
||||
int main() {
|
||||
/* set_debug_traps(); setup exception handlers*/
|
||||
/* char buf[3]; */
|
||||
/* buf[0]=user_serial_getc(1); */
|
||||
/* buf[1]=user_serial_getc(1); */
|
||||
/* buf[2]='\0'; */
|
||||
/* serial_print(buf); */
|
||||
/* register_exception_handler(user_handler); */
|
||||
/* breakpoint(); */
|
||||
long size=initrd_sz();
|
||||
char* initrd=malloc(size);
|
||||
initrd_get(initrd);
|
||||
@ -122,6 +188,8 @@ int main() {
|
||||
if (!stdout) {
|
||||
serial_print("Could not open the VGA device file!\n");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("VGA OK\n");
|
||||
}
|
||||
posix_spawn(NULL,"/initrd/ps2",NULL,NULL,NULL,NULL);
|
||||
// posix_spawn(NULL,"/initrd/pci",NULL,NULL,NULL,NULL);
|
||||
|
4556
initrd_drv/dump
Normal file
4556
initrd_drv/dump
Normal file
File diff suppressed because it is too large
Load Diff
125
install.rb
Normal file → Executable file
125
install.rb
Normal file → Executable file
@ -1,94 +1,91 @@
|
||||
#! /usr/bin/env ruby
|
||||
require "tempfile"
|
||||
usbdisks=`for devlink in /dev/disk/by-id/usb*; do readlink -f ${devlink}; done`
|
||||
raws=usbdisks.split("\n")
|
||||
parts=[]
|
||||
for disk in raws
|
||||
if /(\w+)\d+/.match disk
|
||||
parts.push disk
|
||||
end
|
||||
# frozen_string_literal: true
|
||||
require 'tempfile'
|
||||
usbdisks = `for devlink in /dev/disk/by-id/usb*; do readlink -f ${devlink}; done`
|
||||
raws = usbdisks.split("\n")
|
||||
parts = []
|
||||
raws.each do |disk|
|
||||
parts.push disk if /(\w+)\d+/.match disk
|
||||
end
|
||||
for disk in raws
|
||||
if /(\w+)\d+/.match disk
|
||||
raws.delete("/dev/#{$1}")
|
||||
end
|
||||
raws.each do |disk|
|
||||
raws.delete("/dev/#{$1}") if /(\w+)\d+/.match disk
|
||||
end
|
||||
if raws.length==0
|
||||
puts "No disks detected. Aborting."
|
||||
if raws.length == 0
|
||||
puts 'No disks detected. Aborting.'
|
||||
exit 1
|
||||
end
|
||||
if parts.length>1
|
||||
puts "Multiple partitions detected."
|
||||
i=0
|
||||
for part in parts
|
||||
if parts.length > 1
|
||||
puts 'Multiple partitions detected.'
|
||||
i = 0
|
||||
parts.each do |part|
|
||||
puts "#{i}: #{part}"
|
||||
i+=1
|
||||
i += 1
|
||||
end
|
||||
print "Please choose partition to install to:"
|
||||
num=gets.chomp.to_i
|
||||
part=parts[num]
|
||||
print 'Please choose partition to install to:'
|
||||
num = gets.chomp.to_i
|
||||
part = parts[num]
|
||||
/(\w+)\d+/.match part
|
||||
raw="/dev/#{$1}"
|
||||
elsif parts.length==0
|
||||
puts "No partitions detected."
|
||||
i=0
|
||||
for raw in raws
|
||||
raw = "/dev/#{$1}"
|
||||
elsif parts.length == 0
|
||||
puts 'No partitions detected.'
|
||||
i = 0
|
||||
raws.each do |raw|
|
||||
puts "#{i}: #{raw}"
|
||||
i+=1
|
||||
i += 1
|
||||
end
|
||||
print "Please choose disk to install to:"
|
||||
num=gets.chomp.to_i
|
||||
raw=raws[num]
|
||||
print "Getting disk size..."
|
||||
origsize=`sudo blockdev --getsize64 #{raw}`.chomp.to_i
|
||||
unit="MB"
|
||||
fullsize=(origsize/1024.to_f)/1024
|
||||
if fullsize%1024==0 or fullsize>2048
|
||||
fullsize=fullsize/1024.to_f
|
||||
unit="GB"
|
||||
print 'Please choose disk to install to:'
|
||||
num = gets.chomp.to_i
|
||||
raw = raws[num]
|
||||
print 'Getting disk size...'
|
||||
origsize = `sudo blockdev --getsize64 #{raw}`.chomp.to_i
|
||||
unit = 'MB'
|
||||
fullsize = (origsize / 1024.to_f) / 1024
|
||||
if (fullsize % 1024 == 0) || (fullsize > 2048)
|
||||
fullsize = fullsize / 1024.to_f
|
||||
unit = 'GB'
|
||||
end
|
||||
fullsize=fullsize.floor(1)
|
||||
fullsize = fullsize.floor(1)
|
||||
puts "#{fullsize}#{unit}"
|
||||
print "Partition size: (return for whole disk)"
|
||||
size=gets.chomp.downcase
|
||||
if size.match /(\d)+m/ or size.match /(\d+)mb/
|
||||
size=(size.to_i)*1024*1024
|
||||
elsif size.match /(\d)+g/ or size.match /(\d+)gb/
|
||||
size=(size.to_i)*1024*1024*1024
|
||||
elsif size==""
|
||||
size=origsize
|
||||
print 'Partition size: (return for whole disk)'
|
||||
size = gets.chomp.downcase
|
||||
if size.match(/(\d)+m/)) || size.match(/(\d+)mb/))
|
||||
size = size.to_i * 1024 * 1024
|
||||
elsif size.match(/(\d)+g/)) || size.match(/(\d+)gb/))
|
||||
size = size.to_i * 1024 * 1024 * 1024
|
||||
elsif size == ''
|
||||
size = origsize
|
||||
else
|
||||
puts "Could not parse size. Aborting."
|
||||
puts 'Could not parse size. Aborting.'
|
||||
exit 1
|
||||
end
|
||||
sfdisk_input="label: dos\n- #{size/1024}KiB L"
|
||||
tmp=Tempfile.new("myosinstall")
|
||||
sfdisk_input = "label: dos\n- #{size / 1024}KiB L"
|
||||
tmp = Tempfile.new('myosinstall')
|
||||
tmp.puts sfdisk_input
|
||||
tmp.close
|
||||
print "Partitioning..."
|
||||
print 'Partitioning...'
|
||||
`cat #{tmp.path} | sudo sfdisk #{raw} 2>/dev/null`
|
||||
puts "Done"
|
||||
puts 'Done'
|
||||
tmp.unlink
|
||||
exit 1
|
||||
puts `sudo mkfs.ext2 #{raw}`
|
||||
part="#{raw}1"
|
||||
raw="#{raw}"
|
||||
part = "#{raw}1"
|
||||
raw = raw.to_s
|
||||
else
|
||||
part=parts[0]
|
||||
part = parts[0]
|
||||
/(\w+)\d+/.match parts[0]
|
||||
raw="/dev/#{$1}"
|
||||
raw = "/dev/#{$1}"
|
||||
end
|
||||
`mkdir -p usb`
|
||||
print "Mounting the disk..."
|
||||
print 'Mounting the disk...'
|
||||
`sudo mount #{part} usb`
|
||||
puts "Done"
|
||||
if !File.exists?("usb/boot")
|
||||
puts "Installing GRUB..."
|
||||
puts 'Done'
|
||||
if !File.exist?('usb/boot')
|
||||
puts 'Installing GRUB...'
|
||||
`sudo grub-install --boot-directory=usb/boot #{raw}`
|
||||
end
|
||||
print "Installing the OS..."
|
||||
print 'Installing the OS...'
|
||||
`sudo cp -r /vagrant/sysroot/* usb`
|
||||
puts "Done"
|
||||
print "Umounting disk..."
|
||||
puts 'Done'
|
||||
print 'Umounting disk...'
|
||||
`sudo umount usb`
|
||||
puts "Done"
|
||||
puts 'Done'
|
||||
|
@ -29,6 +29,10 @@ typedef struct {
|
||||
|
||||
static isr_handler_info irq_handlers[16]={0}; //!< Handlers for the PIC interrupts
|
||||
|
||||
static char waiting_for_exception_return[32768]={0};
|
||||
static registers_t* exception_return_value[32768]={0};
|
||||
static void* exception_handler_address[32768]={NULL};
|
||||
|
||||
void isr_install() {
|
||||
idt_set_gate(0,(uint32_t)isr0);
|
||||
idt_set_gate(1,(uint32_t)isr1);
|
||||
@ -157,10 +161,6 @@ void isr_handler(registers_t* r) {
|
||||
char str[11];
|
||||
int_to_ascii(tasking_get_PID(),str);
|
||||
serial_write_string(str);
|
||||
serial_write_string(" and address ");
|
||||
str[0]='\0';
|
||||
hex_to_ascii(r->eip,str);
|
||||
serial_write_string(str);
|
||||
if (r->err_code==0) {
|
||||
serial_write_string(", kernel process tried to read a non-present page entry at address ");
|
||||
} else if (r->err_code==1) {
|
||||
@ -181,12 +181,10 @@ void isr_handler(registers_t* r) {
|
||||
str[0]='\0';
|
||||
hex_to_ascii((unsigned int)addr,str);
|
||||
serial_write_string(str);
|
||||
serial_write_string(".");
|
||||
serial_write_string(" Stack is at ");
|
||||
str[0]='\0';
|
||||
hex_to_ascii(r->useresp,str);
|
||||
serial_write_string(str);
|
||||
serial_write_string(".\n");
|
||||
serial_printf("EAX: %x EBX: %x ECX: %x EDX: %x\n", r->eax, r->ebx, r->ecx, r->edx);
|
||||
serial_printf("ESI: %x EDI: %x ESP: %x EBP: %x\n", r->esi, r->edi, r->useresp, r->ebp);
|
||||
serial_printf("EIP: %x, EFLAGS: %x", r->eip, r->eflags);
|
||||
// if ((r->err_code&1)==0) {
|
||||
// // int dir_entry=(addr&0xFFC00000)>>22;
|
||||
// // int table_entry=(addr&0x3FF000)>12;
|
||||
@ -298,10 +296,39 @@ void isr_handler(registers_t* r) {
|
||||
case SYSCALL_REGISTER_IRQ_HANDLER:
|
||||
isr_register_handler((int)r->ebx,tasking_get_PID(),(void*)r->ecx);
|
||||
break;
|
||||
}
|
||||
case SYSCALL_SERIAL_PUTC:
|
||||
serial_putc_port((char)r->ebx,(int)r->ecx);
|
||||
break;
|
||||
case SYSCALL_SERIAL_GETC:
|
||||
r->ebx=serial_getc_port((int)r->ebx);
|
||||
break;
|
||||
case SYSCALL_EXCEPTION_RETURN:
|
||||
serial_printf("RETURNING FROM USER EXCEPTION HANDLER\n");
|
||||
waiting_for_exception_return[tasking_get_PID()]=0;
|
||||
break;
|
||||
case SYSCALL_REGISTER_EXCEPTION_HANDLER:
|
||||
serial_printf("REGISTERING USER EXCEPTION HANDLER\n");
|
||||
exception_handler_address[tasking_get_PID()]=(void*)r->ebx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r->int_no!=3 || exception_handler_address[tasking_get_PID()]==NULL) {
|
||||
return;
|
||||
}
|
||||
if (waiting_for_exception_return[tasking_get_PID()]==1) {
|
||||
serial_printf("Exception handler thread had exception!\n");
|
||||
halt();
|
||||
}
|
||||
serial_printf("CALLING USER EXCEPTION HANDLER\n");
|
||||
waiting_for_exception_return[tasking_get_PID()]=1;
|
||||
if (!exception_return_value[tasking_get_PID()]) {
|
||||
exception_return_value[tasking_get_PID()]=alloc_pages(1);
|
||||
}
|
||||
memcpy(exception_return_value[tasking_get_PID()],r,sizeof(registers_t));
|
||||
tasking_new_thread(exception_handler_address[tasking_get_PID()],tasking_get_PID(),exception_return_value[tasking_get_PID()],1);
|
||||
while (waiting_for_exception_return[tasking_get_PID()]==1) { tasking_yield(); }
|
||||
memcpy(r, exception_return_value[tasking_get_PID()], sizeof(registers_t));
|
||||
}
|
||||
|
||||
|
||||
@ -328,7 +355,9 @@ void irq_handler(registers_t* r) {
|
||||
if(info.pid==0) {
|
||||
((isr_t)info.handler)(r);
|
||||
} else {
|
||||
tasking_new_thread(info.handler,info.pid,(void*)(r->int_no-32),1);
|
||||
registers_t* user_r=alloc_pages(1);
|
||||
memcpy(user_r,r,sizeof(r));
|
||||
tasking_new_thread(info.handler,info.pid,(void*)(r),1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ static int data_ports[4]={0x3f8,0x2f8,0x3e8,0x2e8}; //!< List of the data ports
|
||||
#define LINE_STAT_PORT(com) (DATA_PORT(com)+5) //!< Returns the line status port of a serial port
|
||||
#define SCRATCH_PORT(com) (DATA_PORT(com)+7) //!< Returns the scratch port of a serial port
|
||||
#define IS_TRANSMIT_FIFO_EMPTY(com) (port_byte_in(LINE_STAT_PORT(com))&0x20) //!< Returns whether the trasmit FIFO is empty.
|
||||
#define IS_RECEIVE_FIFO_READY(com) (port_byte_in(LINE_STAT_PORT(com))&0x1) //!< Returns whether the receive FIFO is empty.
|
||||
|
||||
/**
|
||||
* Configure a serial port with a specified baud rate.
|
||||
@ -30,6 +31,7 @@ static void configure(int com, int rate) {
|
||||
port_byte_out(FIFO_PORT(com),0xC7); //Enable & clear FIFOs and set Data Ready interrupt level to 14.
|
||||
port_byte_out(MODEM_CMD_PORT(com),0x03); //Enable DTR and RTS
|
||||
port_byte_out(INT_PORT(com),0x0); //Disable interrupts
|
||||
serial_printf("Port %d configured\n",com);
|
||||
}
|
||||
|
||||
void serial_init() {
|
||||
@ -37,6 +39,10 @@ void serial_init() {
|
||||
if (port_byte_in(SCRATCH_PORT(0))==0xaa) {
|
||||
configure(0,9600);
|
||||
}
|
||||
port_byte_out(SCRATCH_PORT(1),0xaa);
|
||||
if (port_byte_in(SCRATCH_PORT(1))==0xaa) {
|
||||
configure(1,9600);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_putc(char c) {
|
||||
@ -45,3 +51,29 @@ void serial_putc(char c) {
|
||||
while(!IS_TRANSMIT_FIFO_EMPTY(0));
|
||||
port_byte_out(DATA_PORT(0),c);
|
||||
}
|
||||
|
||||
char serial_getc() {
|
||||
/* serial_printf("Port 0 byte read requested\n"); */
|
||||
if (!configured[0]) return 0;
|
||||
/* serial_printf("Port 0 reading byte\n"); */
|
||||
while(!IS_RECEIVE_FIFO_READY(0));
|
||||
/* serial_printf("Port 0 read byte\n"); */
|
||||
return port_byte_in(DATA_PORT(0));
|
||||
}
|
||||
|
||||
void serial_putc_port(char c, int port) {
|
||||
if (!configured[port]) return;
|
||||
if (c=='\n') serial_putc('\r');
|
||||
while(!IS_TRANSMIT_FIFO_EMPTY(port));
|
||||
port_byte_out(DATA_PORT(port),c);
|
||||
}
|
||||
|
||||
char serial_getc_port(int port) {
|
||||
serial_printf("Port %d byte read requested\n",port);
|
||||
if (!configured[port]) return 0;
|
||||
serial_printf("Port %d reading byte\n",port);
|
||||
while(!IS_RECEIVE_FIFO_READY(port));
|
||||
char data = port_byte_in(DATA_PORT(port));
|
||||
serial_printf("Port %d read byte \"%c\" (%x)\n",port, data, data);
|
||||
return data;
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ static int new_kstack() {
|
||||
}
|
||||
|
||||
void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip,char is_irq_handler) {
|
||||
/* serial_printf("Setup kstack for TID %d, PID %d\n", thread->tid, thread->process->pid); */
|
||||
size_t kstack_num=new_kstack();
|
||||
if (kmode) {
|
||||
size_t top_idx=(1024*(kstack_num+1));
|
||||
@ -73,12 +74,14 @@ void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip,
|
||||
user_stack-=2;
|
||||
user_stack[0]=param2;
|
||||
user_stack[1]=param1;
|
||||
/* serial_printf("User stack in address space: %x\n", user_stack); */
|
||||
});
|
||||
if (is_irq_handler) {
|
||||
kstacks[top_idx-3]=(void*)task_init_no_int;
|
||||
} else {
|
||||
kstacks[top_idx-3]=(void*)task_init;
|
||||
}
|
||||
/* serial_printf("User stack outside space: %x\n", user_stack); */
|
||||
kstacks[top_idx-2]=(void*)user_stack;
|
||||
kstacks[top_idx-1]=(void*)eip;
|
||||
}
|
||||
|
@ -11,11 +11,31 @@
|
||||
void serial_init();
|
||||
|
||||
/**
|
||||
* Write a character to the serial port
|
||||
* Write a character to serial port 0
|
||||
* \param c The character to write
|
||||
*/
|
||||
void serial_putc(char c);
|
||||
|
||||
/**
|
||||
* Read a character from serial port 0
|
||||
* \return The character read from the serial port
|
||||
*/
|
||||
char serial_getc();
|
||||
|
||||
/**
|
||||
* Write a character to the specified serial port
|
||||
* \param c The character to write
|
||||
* \param port The port number to write to
|
||||
*/
|
||||
void serial_putc_port(char c, int port);
|
||||
|
||||
/**
|
||||
* Read a character from the specified serial port
|
||||
* \return The character read from the serial port
|
||||
* \param port The port number to read from
|
||||
*/
|
||||
char serial_getc_port(int port);
|
||||
|
||||
/**
|
||||
* Write a string to the serial port
|
||||
* \param s The string to write
|
||||
|
@ -117,14 +117,14 @@ void kmain(struct multiboot_boot_header_tag* hdr) {
|
||||
copy_data(address_space,ptr,pheader.memsz,(void*)pheader.vaddr);
|
||||
}
|
||||
create_proc((void*)header.entry,address_space,NULL,NULL);
|
||||
// for (int i=0;i<4;i++) {
|
||||
// yield();
|
||||
// }
|
||||
// unblock_thread(1,0);
|
||||
// for (int i=0;i<4;i++) {
|
||||
// yield();
|
||||
// }
|
||||
// for (;;);
|
||||
for (int i=0;i<4;i++) {
|
||||
yield();
|
||||
}
|
||||
unblock_thread(1,0);
|
||||
for (int i=0;i<4;i++) {
|
||||
yield();
|
||||
}
|
||||
for (;;);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
/**
|
||||
* \file
|
||||
*/
|
||||
|
||||
#include "cpu/halt.h"
|
||||
#include "cpu/paging.h"
|
||||
#include "cpu/serial.h"
|
||||
@ -10,6 +6,7 @@
|
||||
#include "tasking.h"
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include "rpc.h"
|
||||
|
||||
#define MAX_PROCS 32768 //!< Maximum number of processes that can be running at a time
|
||||
#define HAS_UNBLOCKED_THREADS(proc) (proc->num_threads!=proc->num_threads_blocked) //!< Macro to check whethe a process has unblocked threads
|
||||
@ -22,12 +19,13 @@ char proc_schedule_bmap[MAX_PROCS/8]; //!< Bitmap of what processes are schedule
|
||||
Thread* current_thread; //!< Currently running thread
|
||||
static Thread* ready_to_run_head=NULL; //!< Head of the linked list of ready to run threads
|
||||
static Thread* ready_to_run_tail=NULL; //!< Tail of the linked list of ready to run threads
|
||||
static Thread* thread_to_be_freed; //!< Thread that exited and needs to be freed
|
||||
|
||||
/**
|
||||
* Check whether a process is scheduled
|
||||
* \param index The PID to check
|
||||
* \return whether the process is scheduled
|
||||
*/
|
||||
*/
|
||||
static char is_proc_scheduled(pid_t index) {
|
||||
size_t byte=index/8;
|
||||
size_t bit=index%8;
|
||||
@ -38,7 +36,7 @@ static char is_proc_scheduled(pid_t index) {
|
||||
/**
|
||||
* Mark a process as scheduled
|
||||
* \param index The PID to mark
|
||||
*/
|
||||
*/
|
||||
static void mark_proc_scheduled(pid_t index) {
|
||||
if (is_proc_scheduled(index)) {
|
||||
serial_printf("Attempt to schedule a thread in a process with a scheduled thread! (PID %d)\n",index);
|
||||
@ -52,7 +50,7 @@ static void mark_proc_scheduled(pid_t index) {
|
||||
/**
|
||||
* Unmark a process as scheduled
|
||||
* \param index The PID to unmark
|
||||
*/
|
||||
*/
|
||||
static void unmark_proc_scheduled(pid_t index) {
|
||||
size_t byte=index/8;
|
||||
size_t bit=index%8;
|
||||
@ -62,7 +60,7 @@ static void unmark_proc_scheduled(pid_t index) {
|
||||
/**
|
||||
* Schedules a thread if the thread's prcess does not have a scheduled thread
|
||||
* \param thread The thread to schedule
|
||||
*/
|
||||
*/
|
||||
void schedule_thread(Thread* thread) {
|
||||
if(!is_proc_scheduled(thread->process->pid)) {
|
||||
if (ready_to_run_head) {
|
||||
@ -120,17 +118,17 @@ void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,v
|
||||
proc->first_thread=thread;
|
||||
setup_kstack(thread,param1,param2,kmode,eip,is_irq_handler);
|
||||
schedule_thread(thread);
|
||||
serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid);
|
||||
serial_printf("Structure values:\n");
|
||||
serial_printf("kernel_esp=%x\n",thread->kernel_esp);
|
||||
serial_printf("kernel_esp_top=%x\n",thread->kernel_esp_top);
|
||||
serial_printf("address_space=%x\n",thread->address_space);
|
||||
serial_printf("tid=%d\n",thread->tid);
|
||||
serial_printf("state=%d\n",thread->state);
|
||||
serial_printf("next_thread_in_process=%x\n",thread->next_thread_in_process);
|
||||
serial_printf("next_ready_to_run=%x\n",thread->next_ready_to_run);
|
||||
serial_printf("prev_ready_to_run=%x\n",thread->prev_ready_to_run);
|
||||
serial_printf("process=%x\n",thread->process);
|
||||
/* serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid); */
|
||||
/* serial_printf("Structure values:\n"); */
|
||||
/* serial_printf("kernel_esp=%x\n",thread->kernel_esp); */
|
||||
/* serial_printf("kernel_esp_top=%x\n",thread->kernel_esp_top); */
|
||||
/* serial_printf("address_space=%x\n",thread->address_space); */
|
||||
/* serial_printf("tid=%d\n",thread->tid); */
|
||||
/* serial_printf("state=%d\n",thread->state); */
|
||||
/* serial_printf("next_thread_in_process=%x\n",thread->next_thread_in_process); */
|
||||
/* serial_printf("next_ready_to_run=%x\n",thread->next_ready_to_run); */
|
||||
/* serial_printf("prev_ready_to_run=%x\n",thread->prev_ready_to_run); */
|
||||
/* serial_printf("process=%x\n",thread->process); */
|
||||
}
|
||||
|
||||
void tasking_init() {
|
||||
@ -167,15 +165,15 @@ pid_t tasking_new_thread(void* start,pid_t pid,void* param,char is_irq_handler)
|
||||
* \param thread The start thread
|
||||
* \param thread_to_skip A thread to skip even if it's ready
|
||||
* \return the next ready thread
|
||||
*/
|
||||
*/
|
||||
static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
#define HELPER \
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
#define HELPER \
|
||||
while (thread&&(thread->state!=THREAD_READY||thread==thread_to_skip)) { \
|
||||
thread=thread->next_thread_in_process; \
|
||||
}
|
||||
//end define
|
||||
#endif
|
||||
#endif
|
||||
Thread* start_of_list=thread->process->first_thread;
|
||||
thread=thread->next_thread_in_process;
|
||||
HELPER;
|
||||
@ -184,13 +182,13 @@ static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
||||
HELPER;
|
||||
}
|
||||
return thread;
|
||||
#undef HELPER
|
||||
#undef HELPER
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a thread and schedule the next ready thread in the current process, if there is one.
|
||||
* \param thread The thread to switch to
|
||||
*/
|
||||
*/
|
||||
void switch_to_thread(Thread* thread) {
|
||||
// Unlink the thread from the list of ready-to-run threads
|
||||
if (thread!=ready_to_run_head) {
|
||||
@ -220,13 +218,24 @@ void switch_to_thread(Thread* thread) {
|
||||
schedule_thread(current_thread_next_ready);
|
||||
}
|
||||
thread->state=THREAD_RUNNING;
|
||||
// serial_printf("Switching to PID %d TID %d.\n",thread->process->pid,thread->tid);
|
||||
serial_printf("Switching to PID %d TID %d.\n",thread->process->pid,thread->tid);
|
||||
switch_to_thread_asm(thread);
|
||||
if (thread_to_be_freed) {
|
||||
serial_printf("Freeing PID %d TID %d.\n",thread_to_be_freed->process->pid,thread_to_be_freed->tid);
|
||||
if (thread_to_be_freed->prev_thread_in_process) {
|
||||
thread_to_be_freed->prev_thread_in_process->next_thread_in_process = thread_to_be_freed->next_thread_in_process;
|
||||
}
|
||||
if (thread_to_be_freed->next_thread_in_process) {
|
||||
thread_to_be_freed->next_thread_in_process->prev_thread_in_process = thread_to_be_freed->prev_thread_in_process;
|
||||
}
|
||||
free_kstack(thread_to_be_freed->kernel_esp);
|
||||
kfree(thread_to_be_freed);
|
||||
}
|
||||
}
|
||||
|
||||
void tasking_yield() {
|
||||
if (ready_to_run_head) {
|
||||
// serial_printf("Attempting to switch to PID %d TID %d\n",ready_to_run_head->process->pid,ready_to_run_head->tid);
|
||||
serial_printf("Attempting to switch to PID %d TID %d\n",ready_to_run_head->process->pid,ready_to_run_head->tid);
|
||||
switch_to_thread(ready_to_run_head);
|
||||
} else {
|
||||
if (NUM_UNBLOCKED_THREADS(current_thread->process)>1) {
|
||||
@ -244,11 +253,11 @@ void tasking_yield() {
|
||||
for(;;);
|
||||
halt();
|
||||
} else {
|
||||
// serial_printf("All threads in all processes blocked, waiting for an IRQ which unblocks a thread\n");
|
||||
serial_printf("All threads in all processes blocked, waiting for an IRQ which unblocks a thread\n");
|
||||
// All threads in all processes blocked, so wait for an IRQ whose handler unblocks a thread.
|
||||
do { wait_for_unblocked_thread_asm(); } while (ready_to_run_head==NULL);
|
||||
}
|
||||
// serial_printf("Attempting to switch to PID %d TID %d\n",ready_to_run_head->process->pid,ready_to_run_head->tid);
|
||||
serial_printf("Attempting to switch to PID %d TID %d\n",ready_to_run_head->process->pid,ready_to_run_head->tid);
|
||||
switch_to_thread(ready_to_run_head);
|
||||
}
|
||||
}
|
||||
@ -295,7 +304,7 @@ void tasking_block(thread_state newstate) {
|
||||
* \param pid The PID of the thread
|
||||
* \param tid The TID of the thread
|
||||
* \return the thread wih the specified PID and TID
|
||||
*/
|
||||
*/
|
||||
static Thread* get_thread(pid_t pid,pid_t tid) {
|
||||
if (processes[pid].num_threads==0) {
|
||||
serial_printf("PID %d does not exist!\n",pid);
|
||||
@ -319,7 +328,7 @@ static Thread* get_thread(pid_t pid,pid_t tid) {
|
||||
}
|
||||
|
||||
void tasking_unblock(pid_t pid,pid_t tid) {
|
||||
// serial_printf("Unblocking PID %d TID %d\n",pid,tid);
|
||||
serial_printf("Unblocking PID %d TID %d\n",pid,tid);
|
||||
Thread* thread=get_thread(pid,tid);
|
||||
if (thread==NULL) {
|
||||
return;
|
||||
@ -334,7 +343,7 @@ void tasking_unblock(pid_t pid,pid_t tid) {
|
||||
}
|
||||
|
||||
void tasking_exit(int code) {
|
||||
// serial_printf("PID %d is exiting with code %d.\n",current_thread->process->pid,code);
|
||||
serial_printf("PID %d is exiting with code %d.\n",current_thread->process->pid,code);
|
||||
if (ready_to_run_head&&SAME_PROC(ready_to_run_head,current_thread)) {
|
||||
ready_to_run_head=ready_to_run_head->next_ready_to_run;
|
||||
if (ready_to_run_head==NULL) {
|
||||
@ -363,7 +372,15 @@ void tasking_exit(int code) {
|
||||
for (Thread* thread=current_thread->process->first_thread;thread!=NULL;thread=thread->next_thread_in_process) {
|
||||
if (thread->state!=THREAD_EXITED) {
|
||||
thread->state=THREAD_EXITED;
|
||||
free_kstack(thread->kernel_esp_top);
|
||||
if (thread==current_thread->process->first_thread && kernel_rpc_is_init(current_thread->process->pid)) {
|
||||
continue;
|
||||
}
|
||||
if (thread!=current_thread) {
|
||||
free_kstack(thread->kernel_esp);
|
||||
kfree(thread);
|
||||
} else {
|
||||
thread_to_be_freed = current_thread;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_thread->process->num_threads_blocked=current_thread->process->num_threads;
|
||||
@ -398,7 +415,9 @@ void* tasking_get_rpc_ret_buf() {
|
||||
}
|
||||
|
||||
void tasking_thread_exit() {
|
||||
serial_printf("PID %d TID %d is exiting\n",current_thread->process->pid,current_thread->tid);
|
||||
tasking_block(THREAD_EXITED);
|
||||
thread_to_be_freed=current_thread;
|
||||
}
|
||||
|
||||
char tasking_check_proc_exists(pid_t pid) {
|
||||
|
0
libc/cpu/dbg.h
Normal file
0
libc/cpu/dbg.h
Normal file
10
libc/cpu/irq.c
Normal file
10
libc/cpu/irq.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <sys/syscalls.h>
|
||||
#define QUAUX(X) #X
|
||||
#define QU(X) QUAUX(X)
|
||||
|
||||
void register_irq_handler(int irq_no,void* handler) {
|
||||
asm volatile(" \
|
||||
mov $" QU(SYSCALL_REGISTER_IRQ_HANDLER) ", %%eax; \
|
||||
int $80; \
|
||||
"::"b"(irq_no),"c"(handler));
|
||||
}
|
11
libc/cpu/irq.h
Normal file
11
libc/cpu/irq.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef IRQ_H
|
||||
#define IRQ_H
|
||||
|
||||
/**
|
||||
* Registers the current process as an interrupt handler
|
||||
* \param int_no The interrupt to register for
|
||||
* \param handler The address of the handler to register
|
||||
*/
|
||||
void register_irq_handler(int irq_no,void* handler);
|
||||
|
||||
#endif
|
16
libc/dbg.c
16
libc/dbg.c
@ -9,3 +9,19 @@ void serial_print(char* str) {
|
||||
int $80; \
|
||||
"::"b"(str));
|
||||
}
|
||||
|
||||
void user_serial_putc(char c, int port) {
|
||||
asm volatile(" \
|
||||
mov $" QU(SYSCALL_SERIAL_PUTC) ", %%eax; \
|
||||
int $80; \
|
||||
"::"b"(c),"c"(port));
|
||||
}
|
||||
|
||||
char user_serial_getc(int port) {
|
||||
char c;
|
||||
asm volatile(" \
|
||||
mov $" QU(SYSCALL_SERIAL_GETC) ", %%eax; \
|
||||
int $80; \
|
||||
":"=b"(c):"b"(port));
|
||||
return c;
|
||||
}
|
||||
|
13
libc/dbg.h
13
libc/dbg.h
@ -12,4 +12,17 @@
|
||||
*/
|
||||
void serial_print(char* str);
|
||||
|
||||
/**
|
||||
* Write a character to the specified serial port
|
||||
* \param c The character to write
|
||||
* \param port The port number to write to
|
||||
*/
|
||||
void user_serial_putc(char c, int port);
|
||||
|
||||
/**
|
||||
* Read a character from the specified serial port
|
||||
* \return The character read from the serial port
|
||||
* \param port The port number to read from
|
||||
*/
|
||||
char user_serial_getc(int port);
|
||||
#endif
|
||||
|
20
libc/exception.c
Normal file
20
libc/exception.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <sys/syscalls.h>
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define QUAUX(X) #X
|
||||
#define QU(X) QUAUX(X)
|
||||
|
||||
void exception_return() {
|
||||
asm volatile(" \
|
||||
mov $" QU(SYSCALL_EXCEPTION_RETURN) ", %%eax; \
|
||||
int $80; \
|
||||
":);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
void register_exception_handler(void* handler) {
|
||||
asm volatile(" \
|
||||
mov $" QU(SYSCALL_REGISTER_EXCEPTION_HANDLER) ", %%eax; \
|
||||
int $80; \
|
||||
"::"b"(handler));
|
||||
}
|
@ -10,6 +10,7 @@ int posix_spawn(pid_t* pid, const char* path, const posix_spawn_file_actions_t*
|
||||
char* const argv[], char* const envp[]) {
|
||||
FILE* image=fopen((char*)path,"r");
|
||||
elf_header header;
|
||||
serial_print("Read magic number\n");
|
||||
fread(&header,sizeof(elf_header),1,image);
|
||||
if (header.magic!=ELF_MAGIC) {
|
||||
serial_print("Bad magic number (");
|
||||
|
10
libc/stdio.c
10
libc/stdio.c
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \file
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <serdes.h>
|
||||
@ -17,7 +17,7 @@ FILE* stderr=NULL; //!< Standard error
|
||||
/**
|
||||
* Initialize stdio.
|
||||
* Must not be called by user code.
|
||||
*/
|
||||
*/
|
||||
void __stdio_init() {
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ FILE* fopen(char* filename,char* mode) {
|
||||
* \param c The character to write
|
||||
* \param stream The stream to write to
|
||||
* \returns the written character, or EOF on failure
|
||||
*/
|
||||
*/
|
||||
int putc(int c, FILE* stream) __attribute__ ((alias ("fputc")));
|
||||
|
||||
int fputc(int c, FILE* stream) {
|
||||
@ -64,7 +64,7 @@ int fputc(int c, FILE* stream) {
|
||||
* Gets a character from a file
|
||||
* \param stream The file to read from
|
||||
* \returns the read character, or EOF if the read fails
|
||||
*/
|
||||
*/
|
||||
int getc(FILE* stream) __attribute__ ((alias ("fgetc")));
|
||||
|
||||
int fgetc(FILE* stream) {
|
||||
@ -141,6 +141,8 @@ int fputs(const char* s, FILE* stream) {
|
||||
}
|
||||
|
||||
size_t fwrite(void* buffer_ptr,size_t size,size_t count,FILE* stream) {
|
||||
/* serial_print(buffer_ptr); */
|
||||
/* return size*count; */
|
||||
serdes_state state={0};
|
||||
serialize_ptr(stream->fs_data,&state);
|
||||
serialize_int(size*count,&state);
|
||||
|
@ -30,4 +30,10 @@
|
||||
#define SYSCALL_RPC_IS_INIT 22
|
||||
#define SYSCALL_REGISTER_IRQ_HANDLER 23
|
||||
|
||||
#define SYSCALL_SERIAL_PUTC 24
|
||||
#define SYSCALL_SERIAL_GETC 25
|
||||
|
||||
#define SYSCALL_EXCEPTION_RETURN 27
|
||||
#define SYSCALL_REGISTER_EXCEPTION_HANDLER 28
|
||||
|
||||
#endif
|
||||
|
101
network.rb
101
network.rb
@ -1,65 +1,64 @@
|
||||
require "socket"
|
||||
s=TCPServer.new("localhost",3000)
|
||||
c=s.accept
|
||||
udpsocks=[]
|
||||
tcpsocks=[]
|
||||
next_sock=0
|
||||
puts "Connection established"
|
||||
while true
|
||||
ch=c.getc
|
||||
if ch==nil
|
||||
next
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'socket'
|
||||
s = TCPServer.new('localhost', 3000)
|
||||
c = s.accept
|
||||
udpsocks = []
|
||||
tcpsocks = []
|
||||
next_sock = 0
|
||||
puts 'Connection established'
|
||||
loop do
|
||||
ch = c.getc
|
||||
next if ch.nil?
|
||||
|
||||
cmd = ch.ord
|
||||
c.print [192, 168, 0, 10].pack('CCCC') if cmd.zero?
|
||||
if cmd == 1
|
||||
sock = UDPSocket.new
|
||||
sock.bind('10.0.0.180', 0)
|
||||
c.print [next_sock, sock.addr[1]].pack('L<L<')
|
||||
udpsocks[next_sock] = sock
|
||||
next_sock += 1
|
||||
end
|
||||
cmd=ch.ord
|
||||
if cmd==0
|
||||
c.print [192,168,0,10].pack("CCCC")
|
||||
if cmd == 4
|
||||
info = c.read(12).unpack('L<CCCCS<S<')
|
||||
msg = c.read(info[6])
|
||||
udpsocks[info[0]].send(msg, 0, "#{info[1]}.#{info[2]}.#{info[3]}.#{info[4]}", info[5])
|
||||
end
|
||||
if cmd==1
|
||||
sock=UDPSocket.new()
|
||||
sock.bind("10.0.0.180",0)
|
||||
c.print [next_sock,sock.addr[1]].pack("L<L<")
|
||||
udpsocks[next_sock]=sock
|
||||
next_sock+=1;
|
||||
end
|
||||
if cmd==4
|
||||
info=c.read(12).unpack("L<CCCCS<S<")
|
||||
msg=c.read(info[6])
|
||||
udpsocks[info[0]].send(msg,0,"#{info[1]}.#{info[2]}.#{info[3]}.#{info[4]}",info[5])
|
||||
end
|
||||
if cmd==5
|
||||
id=c.read(4).unpack("L<")[0]
|
||||
msg=udpsocks[id].recv(65536)
|
||||
if msg==""
|
||||
c.print [0].pack("L<")
|
||||
if cmd == 5
|
||||
id = c.read(4).unpack1('L<')
|
||||
msg = udpsocks[id].recv(65_536)
|
||||
if msg == ''
|
||||
c.print [0].pack('L<')
|
||||
else
|
||||
c.print [msg.length].pack("L<")
|
||||
c.print [msg.length].pack('L<')
|
||||
c.print msg
|
||||
end
|
||||
end
|
||||
if cmd==6
|
||||
id=c.read(4).unpack("L<")[0]
|
||||
udpsocks[id]=nil
|
||||
if cmd == 6
|
||||
id = c.read(4).unpack1('L<')
|
||||
udpsocks[id] = nil
|
||||
end
|
||||
if cmd==7
|
||||
info=c.read(6).unpack("CCCCS<")
|
||||
sock=TCPSocket.new("#{info[0]}.#{info[1]}.#{info[2]}.#{info[3]}",info[4])
|
||||
c.print [next_sock].pack("L<")
|
||||
tcpsocks[next_sock]=sock
|
||||
next_sock+=1;
|
||||
if cmd == 7
|
||||
info = c.read(6).unpack('CCCCS<')
|
||||
sock = TCPSocket.new("#{info[0]}.#{info[1]}.#{info[2]}.#{info[3]}", info[4])
|
||||
c.print [next_sock].pack('L<')
|
||||
tcpsocks[next_sock] = sock
|
||||
next_sock += 1
|
||||
end
|
||||
if cmd==8
|
||||
info=c.read(6).unpack("L<S<")
|
||||
msg=c.read(info[1])
|
||||
if cmd == 8
|
||||
info = c.read(6).unpack('L<S<')
|
||||
msg = c.read(info[1])
|
||||
tcpsocks[info[0]].print msg
|
||||
end
|
||||
if cmd==9
|
||||
id=c.read(4).unpack("L<")[0]
|
||||
if !tcpsocks[id].ready? and tcpsocks[id].closed?
|
||||
c.print [0].pack("L<")
|
||||
next unless cmd == 9
|
||||
|
||||
id = c.read(4).unpack1('L<')
|
||||
if !tcpsocks[id].ready? && tcpsocks[id].closed?
|
||||
c.print [0].pack('L<')
|
||||
else
|
||||
msg=tcpsocks[id].gets
|
||||
c.print [msg.length].pack("L<")
|
||||
msg = tcpsocks[id].gets
|
||||
c.print [msg.length].pack('L<')
|
||||
c.print msg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
13
ps2/Makefile
Normal file
13
ps2/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
C_SOURCES = $(wildcard *.c)
|
||||
OBJ = $(C_SOURCES:.c=.o )
|
||||
CFLAGS = -Wall -g
|
||||
CC = i386-myos-gcc
|
||||
|
||||
ps2: $(OBJ) ../libc/*
|
||||
@$(CC) -o $@ $(CFLAGS) $(OBJ)
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
@rm -rf *.o init
|
81
ps2/keyboard.c
Normal file
81
ps2/keyboard.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include "ps2.h"
|
||||
#include <rpc.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <cpu/irq.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BACKSPACE 0x0E
|
||||
#define ENTER 0x1C
|
||||
#define CAPS 0x3A
|
||||
#define LSHIFT 0x2A
|
||||
#define RSHIFT 0x36
|
||||
#define LSHIFTUP 0xAA
|
||||
#define RSHIFTUP 0xB6
|
||||
|
||||
const char *sc_name[] = { "ERROR", "Esc", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E",
|
||||
"R", "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Lctrl",
|
||||
"A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "`",
|
||||
"LShift", "\\", "Z", "X", "C", "V", "B", "N", "M", ",", ".",
|
||||
"/", "RShift", "Keypad *", "LAlt", "Spacebar"};
|
||||
const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y',
|
||||
'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g',
|
||||
'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v',
|
||||
'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '};
|
||||
const char sc_caps_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
|
||||
'U', 'I', 'O', 'P', '[', ']', '?', '?', 'A', 'S', 'D', 'F', 'G',
|
||||
'H', 'J', 'K', 'L', ';', '\'', '`', '?', '\\', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', ',', '.', '/', '?', '?', '?', ' '};
|
||||
const char sc_shift_ascii[] = { '?', '?', '!', '@', '#', '$', '%', '^',
|
||||
'&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
|
||||
'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G',
|
||||
'H', 'J', 'K', 'L', ':', '"', '~', '?', '|', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '};
|
||||
int caps=0;
|
||||
int shift=0;
|
||||
int num_irqs=0;
|
||||
|
||||
static void kbd_handler(int irq) {
|
||||
num_irqs++;
|
||||
char buf[128];
|
||||
int_to_ascii(num_irqs,buf);
|
||||
serial_print("Number of keyboard IRQs: ");
|
||||
serial_print(buf);
|
||||
serial_print("\n");
|
||||
uint8_t scancode=ps2_read_data();
|
||||
if (scancode==BACKSPACE) {
|
||||
putc('\b',stdout);
|
||||
putc(' ',stdout);
|
||||
putc('\b',stdout);
|
||||
} else if (scancode==CAPS) {
|
||||
caps=!caps;
|
||||
} else if (scancode==LSHIFT || scancode==RSHIFT) {
|
||||
shift=1;
|
||||
} else if (scancode==LSHIFTUP || scancode==RSHIFTUP) {
|
||||
shift=0;
|
||||
} else if (scancode==ENTER) {
|
||||
putc('\n',stdout);
|
||||
} else if (scancode<=58) {
|
||||
char letter;
|
||||
if (shift) {
|
||||
letter=sc_shift_ascii[(int)scancode];
|
||||
} else if (caps) {
|
||||
letter=sc_caps_ascii[(int)scancode];
|
||||
} else {
|
||||
letter=sc_ascii[(int)scancode];
|
||||
}
|
||||
putc(letter,stdout);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void init_keyboard(char port) {
|
||||
ps2_send_cmd_w_data_to_device(port,0xF0,1);
|
||||
ps2_send_cmd_to_device(port,0xF4);
|
||||
register_irq_handler(1,&kbd_handler);
|
||||
printf("[INFO] Registered keyboard driver on PS/2 port %d\n",port);
|
||||
}
|
6
ps2/keyboard.h
Normal file
6
ps2/keyboard.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
void init_keyboard(char port);
|
||||
|
||||
#endif
|
119
ps2/main.c
Normal file
119
ps2/main.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <cpu/ports.h>
|
||||
#include "ps2.h"
|
||||
#include "keyboard.h"
|
||||
char ps2_ports_ok[2]={0,0};
|
||||
char ps2_dev_types[2]={0,0};
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
stdout=fopen("/dev/vga","w");
|
||||
ps2_send_cmd(0xAA);
|
||||
uint8_t self_test=ps2_read_data();
|
||||
if (self_test!=0x55) {
|
||||
printf("[INFO] Cannot initialise PS/2 controller\n");
|
||||
return 0;
|
||||
}
|
||||
char is_dual;
|
||||
ps2_send_cmd(0xAD);
|
||||
ps2_send_cmd(0xA7);
|
||||
port_byte_in(PS2_DATA);
|
||||
ps2_send_cmd(0x20);
|
||||
uint8_t cont_cfg=ps2_read_data();
|
||||
cont_cfg=cont_cfg&0xBC;
|
||||
ps2_send_cmd(0x60);
|
||||
ps2_write_data(cont_cfg);
|
||||
if (cont_cfg&0x20) {
|
||||
is_dual=0;
|
||||
} else {
|
||||
ps2_send_cmd(0xA8);
|
||||
ps2_send_cmd(0x20);
|
||||
cont_cfg=ps2_read_data();
|
||||
is_dual=(cont_cfg&0x20)==0;
|
||||
ps2_send_cmd(0xA7);
|
||||
}
|
||||
ps2_send_cmd(0xAB);
|
||||
if (ps2_read_data()==0) {
|
||||
printf("[INFO] First PS/2 port OK\n");
|
||||
ps2_ports_ok[0]=1;
|
||||
} else {
|
||||
printf("[INFO] First PS/2 port not OK\n");
|
||||
}
|
||||
if (is_dual) {
|
||||
ps2_send_cmd(0xA9);
|
||||
if (ps2_read_data()==0) {
|
||||
printf("[INFO] Second PS/2 port OK\n");
|
||||
ps2_ports_ok[1]=1;
|
||||
} else {
|
||||
printf("[INFO] Second PS/2 port not OK\n");
|
||||
}
|
||||
}
|
||||
if (ps2_ports_ok[0]) {
|
||||
ps2_send_cmd(0xAE);
|
||||
ps2_send_cmd_to_device(1,0xF5);
|
||||
port_byte_in(PS2_DATA);
|
||||
ps2_send_cmd(0x20);
|
||||
cont_cfg=ps2_read_data();
|
||||
cont_cfg=cont_cfg|0x1;
|
||||
ps2_send_cmd(0x60);
|
||||
ps2_write_data(cont_cfg);
|
||||
//ps2_ports_ok[0]=ps2_send_cmd_to_device(1,0xFF);
|
||||
}
|
||||
if (ps2_ports_ok[1]) {
|
||||
ps2_send_cmd(0xA8);
|
||||
ps2_send_cmd_to_device(2,0xF5);
|
||||
port_byte_in(PS2_DATA);
|
||||
ps2_send_cmd(0x20);
|
||||
cont_cfg=ps2_read_data();
|
||||
cont_cfg=cont_cfg|0x2;
|
||||
ps2_send_cmd(0x60);
|
||||
ps2_write_data(cont_cfg);
|
||||
//ps2_ports_ok[1]=ps2_send_cmd_to_device(2,0xFF);
|
||||
}
|
||||
if (ps2_ports_ok[0]) {
|
||||
ps2_send_cmd_to_device(1,0xF2);
|
||||
uint8_t first_byte=ps2_read_data();
|
||||
if (first_byte==0xAB) {
|
||||
uint8_t sec_byte=ps2_read_data();
|
||||
if (sec_byte==0x41 || sec_byte==0xC1 || sec_byte==0x83) {
|
||||
printf("[INFO] Keyboard on PS/2 port 1\n");
|
||||
init_keyboard(1);
|
||||
}
|
||||
}
|
||||
if (first_byte==0) {
|
||||
printf("[INFO] Mouse on PS/2 port 1\n");
|
||||
}
|
||||
if (first_byte==3) {
|
||||
printf("[INFO] Mouse w/scroll wheel on PS/2 port 1\n");
|
||||
}
|
||||
if (first_byte==4) {
|
||||
printf("[INFO] 5 button mouse on PS/2 port 1\n");
|
||||
}
|
||||
port_byte_in(PS2_DATA);
|
||||
}
|
||||
if (ps2_ports_ok[1]) {
|
||||
ps2_send_cmd_to_device(2,0xF2);
|
||||
uint8_t first_byte=ps2_read_data();
|
||||
if (first_byte==0xAB) {
|
||||
uint8_t sec_byte=ps2_read_data();
|
||||
if (sec_byte==0x83) {
|
||||
printf("[INFO] Keyboard on PS/2 port 2\n");
|
||||
init_keyboard(2);
|
||||
}
|
||||
}
|
||||
if (first_byte==0) {
|
||||
printf("[INFO] Mouse on PS/2 port 2\n");
|
||||
}
|
||||
if (first_byte==3) {
|
||||
printf("[INFO] Mouse w/scroll wheel on PS/2 port 2\n");
|
||||
}
|
||||
if (first_byte==4) {
|
||||
printf("[INFO] 5 button mouse on PS/2 port 2\n");
|
||||
}
|
||||
port_byte_in(PS2_DATA);
|
||||
}
|
||||
printf("[INFO] PS/2 driver initialized\n");
|
||||
return 0;
|
||||
}
|
75
ps2/ps2.c
Normal file
75
ps2/ps2.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <cpu/ports.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "ps2.h"
|
||||
|
||||
void ps2_send_cmd(uint8_t cmd) {
|
||||
// serial_print("Writing ");
|
||||
// uint8_t str[64];
|
||||
// hex_to_ascii(cmd&0xFF,str);
|
||||
// serial_print(str);
|
||||
// serial_print(" to PS/2 command port\n");
|
||||
while (port_byte_in(PS2_STAT_CMD)&PS2_STAT_INP_BUF);
|
||||
port_byte_out(PS2_STAT_CMD,cmd);
|
||||
}
|
||||
|
||||
uint8_t ps2_read_data() {
|
||||
while (!(port_byte_in(PS2_STAT_CMD)&PS2_STAT_OUT_BUF));
|
||||
uint8_t byte=port_byte_in(PS2_DATA);
|
||||
// serial_print("Read ");
|
||||
// uint8_t str[64];
|
||||
// hex_to_ascii(byte&0xFF,str);
|
||||
// serial_print(str);
|
||||
// serial_print(" from PS/2 data port\n");
|
||||
return byte;
|
||||
}
|
||||
|
||||
void ps2_write_data(uint8_t byte) {
|
||||
// serial_print("Writing ");
|
||||
// uint8_t str[64];
|
||||
// hex_to_ascii((int)byte&0xFF,str);
|
||||
// serial_print(str);
|
||||
// serial_print(" to PS/2 data port\n");
|
||||
while (port_byte_in(PS2_STAT_CMD)&PS2_STAT_INP_BUF);
|
||||
port_byte_out(PS2_DATA,byte);
|
||||
}
|
||||
|
||||
void ps2_write_data_to_device(int port,uint8_t data) {
|
||||
if (port==2) {
|
||||
ps2_send_cmd(0xD4);
|
||||
}
|
||||
ps2_write_data(data);
|
||||
}
|
||||
|
||||
uint8_t ps2_send_cmd_to_device(int port,uint8_t cmd) {
|
||||
while (1) {
|
||||
ps2_write_data_to_device(port,cmd);
|
||||
uint8_t resp=ps2_read_data();
|
||||
if (cmd==0xEE && resp==0xEE) {
|
||||
return 1;
|
||||
}
|
||||
if (resp==0xFA || resp==0xAA) {
|
||||
return 1;
|
||||
}
|
||||
if (resp==0xFC || resp==0xFD) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ps2_send_cmd_w_data_to_device(int port,uint8_t cmd,uint8_t data) {
|
||||
while (1) {
|
||||
ps2_write_data_to_device(port,cmd);
|
||||
ps2_write_data_to_device(port,data);
|
||||
uint8_t resp=ps2_read_data();
|
||||
if (cmd==0xEE && resp==0xEE) {
|
||||
return 1;
|
||||
}
|
||||
if (resp==0xFA || resp==0xAA) {
|
||||
return 1;
|
||||
}
|
||||
if (resp==0xFC || resp==0xFD) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
19
ps2/ps2.h
Normal file
19
ps2/ps2.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef PS2_H
|
||||
#define PS2_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PS2_DATA 0x60
|
||||
#define PS2_STAT_CMD 0x64
|
||||
#define PS2_STAT_OUT_BUF 0x1
|
||||
#define PS2_STAT_INP_BUF 0x2
|
||||
#define PS2_KBD_TYPE 0x1
|
||||
|
||||
void ps2_send_cmd(uint8_t cmd);
|
||||
uint8_t ps2_read_data();
|
||||
void ps2_write_data(uint8_t byte);
|
||||
void ps2_write_data_to_device(int port,uint8_t data);
|
||||
uint8_t ps2_send_cmd_to_device(int port,uint8_t cmd);
|
||||
uint8_t ps2_send_cmd_w_data_to_device(int port,uint8_t cmd,uint8_t data);
|
||||
|
||||
#endif
|
BIN
tar_fs/tar_fs
BIN
tar_fs/tar_fs
Binary file not shown.
15
vfs/main.c
15
vfs/main.c
@ -31,11 +31,18 @@ mount_point* mount_point_list=NULL;
|
||||
fs_type* fs_type_list=NULL;
|
||||
|
||||
void vfs_mount(void* args) {
|
||||
serial_print("MOUNT\n");
|
||||
serdes_state state;
|
||||
start_deserialize(args,&state);
|
||||
char* type=deserialize_str(&state);
|
||||
char* dev=deserialize_str(&state);
|
||||
char* mount_path=deserialize_str(&state);
|
||||
serial_print(type);
|
||||
serial_print("\n");
|
||||
serial_print(dev);
|
||||
serial_print("\n");
|
||||
serial_print(mount_path);
|
||||
serial_print("\n");
|
||||
rpc_deallocate_buf(args,state.sizeorpos);
|
||||
fs_type* fstype=fs_type_list;
|
||||
pid_t fs_pid=0;
|
||||
@ -46,6 +53,7 @@ void vfs_mount(void* args) {
|
||||
}
|
||||
}
|
||||
if (!fs_pid) {
|
||||
serial_print("NO FS PID\n");
|
||||
int err=1;
|
||||
rpc_return(&err,sizeof(int));
|
||||
pthread_exit(NULL);
|
||||
@ -58,6 +66,7 @@ void vfs_mount(void* args) {
|
||||
int* errbuf=malloc(sizeof(int));
|
||||
*errbuf=err;
|
||||
if (err) {
|
||||
serial_print("MOUNT ERROR\n");
|
||||
rpc_return(errbuf,sizeof(int));
|
||||
free(errbuf);
|
||||
pthread_exit(NULL);
|
||||
@ -74,10 +83,13 @@ void vfs_mount(void* args) {
|
||||
}
|
||||
|
||||
void vfs_register_fs(void* args) {
|
||||
serial_print("REGISTER FS\n");
|
||||
serdes_state state;
|
||||
start_deserialize(args,&state);
|
||||
char* name=deserialize_str(&state);
|
||||
pid_t pid=deserialize_int(&state);
|
||||
serial_print(name);
|
||||
serial_print("\n");
|
||||
fs_type* type=malloc(sizeof(fs_type));
|
||||
rpc_deallocate_buf(args,state.sizeorpos);
|
||||
type->name=name;
|
||||
@ -89,9 +101,12 @@ void vfs_register_fs(void* args) {
|
||||
}
|
||||
|
||||
void open(void* args) {
|
||||
serial_print("OPEN\n");
|
||||
serdes_state state;
|
||||
start_deserialize(args,&state);
|
||||
char* path=deserialize_str(&state);
|
||||
serial_print(path);
|
||||
serial_print("\n");
|
||||
rpc_deallocate_buf(args,state.sizeorpos);
|
||||
mount_point* mnt=mount_point_list;
|
||||
mount_point* mnt_pnt=NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user