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
|
set pagination off
|
||||||
target remote localhost:1234
|
target remote localhost:1234
|
||||||
symbol-file kernel/kernel.elf
|
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)
|
NASM = $(shell cat psinfo/$(PLAT)/nasm.txt)
|
||||||
EMU = $(shell cat psinfo/$(PLAT)/emu.txt)
|
EMU = $(shell cat psinfo/$(PLAT)/emu.txt)
|
||||||
CFLAGS = -Isysroot/usr/include -Wextra -Wall -Wno-unused-parameter -g -ffreestanding
|
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)
|
CWD = $(shell pwd)
|
||||||
|
|
||||||
.PHONY: sysroot
|
.PHONY: sysroot
|
||||||
@ -38,11 +38,12 @@ run_nobuild:
|
|||||||
tail -f serout
|
tail -f serout
|
||||||
|
|
||||||
debug: os.iso kernel/kernel.elf
|
debug: os.iso kernel/kernel.elf
|
||||||
@$(EMU) -s $(QFLAGS) &
|
@$(EMU) -s -S $(QFLAGS) &
|
||||||
|
sleep 2
|
||||||
gdb
|
gdb
|
||||||
#gdbgui -g i386-elf-gdb --project $(CWD)
|
#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
|
@cp kernel/kernel.elf sysroot/boot
|
||||||
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
|
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
|
||||||
@grub-mkrescue -o $@ sysroot
|
@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
|
crts: kernel/crt0.o
|
||||||
@cp $^ sysroot/usr/lib
|
@cp $^ sysroot/usr/lib
|
||||||
|
|
||||||
# ps2: crts libc
|
ps2: crts libc
|
||||||
# @cd $@ && make
|
@cd $@ && make
|
||||||
# @cp $@/$@ initrd/$@
|
@cp $@/$@ initrd/$@
|
||||||
|
|
||||||
init: crts libc
|
init: crts libc
|
||||||
@cd $@ && make
|
@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
|
@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)
|
doc: $(C_SOURCES) $(C_HEADERS)
|
||||||
@doxygen kernel/Doxyfile > /dev/null
|
# @doxygen kernel/Doxyfile > /dev/null
|
||||||
@doxygen libc/Doxyfile > /dev/null
|
# @doxygen libc/Doxyfile > /dev/null
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@echo Path to flash drive?; \
|
@echo Path to flash drive?; \
|
||||||
|
12
Vagrantfile
vendored
12
Vagrantfile
vendored
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# -*- mode: ruby -*-
|
# -*- mode: ruby -*-
|
||||||
# vi: set ft=ruby :
|
# vi: set ft=ruby :
|
||||||
|
|
||||||
@ -5,14 +7,14 @@
|
|||||||
# configures the configuration version (we support older styles for
|
# configures the configuration version (we support older styles for
|
||||||
# backwards compatibility). Please don't change it unless you know what
|
# backwards compatibility). Please don't change it unless you know what
|
||||||
# you're doing.
|
# you're doing.
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure('2') do |config|
|
||||||
# The most common configuration options are documented and commented below.
|
# The most common configuration options are documented and commented below.
|
||||||
# For a complete reference, please see the online documentation at
|
# For a complete reference, please see the online documentation at
|
||||||
# https://docs.vagrantup.com.
|
# https://docs.vagrantup.com.
|
||||||
|
|
||||||
# Every Vagrant development environment requires a box. You can search for
|
# Every Vagrant development environment requires a box. You can search for
|
||||||
# boxes at https://vagrantcloud.com/search.
|
# 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
|
# Disable automatic box update checking. If you disable this, then
|
||||||
# boxes will only be checked for updates when the user runs
|
# 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.
|
# backing providers for Vagrant. These expose provider-specific options.
|
||||||
# Example for VirtualBox:
|
# 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
|
# Do not display the VirtualBox GUI when booting the machine
|
||||||
vb.gui = false
|
vb.gui = false
|
||||||
|
|
||||||
# Customize the amount of memory on the VM:
|
# Customize the amount of memory on the VM:
|
||||||
vb.memory = "4096"
|
vb.memory = '4096'
|
||||||
end
|
end
|
||||||
#
|
#
|
||||||
# View the documentation for the provider you are using for more
|
# 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
|
# Enable provisioning with a shell script. Additional provisioners such as
|
||||||
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
||||||
# documentation for more information about their specific syntax and use.
|
# 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
|
apt install ruby
|
||||||
SHELL
|
SHELL
|
||||||
end
|
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];
|
char typeflag[1];
|
||||||
} tar_header;
|
} 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 getsize(const char *in) {
|
||||||
size_t size=0;
|
size_t size=0;
|
||||||
size_t j;
|
size_t j;
|
||||||
@ -92,8 +116,50 @@ char load_proc(size_t datapos,char* initrd) {
|
|||||||
return 1;
|
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() {
|
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();
|
long size=initrd_sz();
|
||||||
char* initrd=malloc(size);
|
char* initrd=malloc(size);
|
||||||
initrd_get(initrd);
|
initrd_get(initrd);
|
||||||
@ -122,6 +188,8 @@ int main() {
|
|||||||
if (!stdout) {
|
if (!stdout) {
|
||||||
serial_print("Could not open the VGA device file!\n");
|
serial_print("Could not open the VGA device file!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
} else {
|
||||||
|
printf("VGA OK\n");
|
||||||
}
|
}
|
||||||
posix_spawn(NULL,"/initrd/ps2",NULL,NULL,NULL,NULL);
|
posix_spawn(NULL,"/initrd/ps2",NULL,NULL,NULL,NULL);
|
||||||
// posix_spawn(NULL,"/initrd/pci",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
|
#! /usr/bin/env ruby
|
||||||
require "tempfile"
|
# frozen_string_literal: true
|
||||||
usbdisks=`for devlink in /dev/disk/by-id/usb*; do readlink -f ${devlink}; done`
|
require 'tempfile'
|
||||||
raws=usbdisks.split("\n")
|
usbdisks = `for devlink in /dev/disk/by-id/usb*; do readlink -f ${devlink}; done`
|
||||||
parts=[]
|
raws = usbdisks.split("\n")
|
||||||
for disk in raws
|
parts = []
|
||||||
if /(\w+)\d+/.match disk
|
raws.each do |disk|
|
||||||
parts.push disk
|
parts.push disk if /(\w+)\d+/.match disk
|
||||||
end
|
|
||||||
end
|
end
|
||||||
for disk in raws
|
raws.each do |disk|
|
||||||
if /(\w+)\d+/.match disk
|
raws.delete("/dev/#{$1}") if /(\w+)\d+/.match disk
|
||||||
raws.delete("/dev/#{$1}")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if raws.length==0
|
if raws.length == 0
|
||||||
puts "No disks detected. Aborting."
|
puts 'No disks detected. Aborting.'
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
if parts.length>1
|
if parts.length > 1
|
||||||
puts "Multiple partitions detected."
|
puts 'Multiple partitions detected.'
|
||||||
i=0
|
i = 0
|
||||||
for part in parts
|
parts.each do |part|
|
||||||
puts "#{i}: #{part}"
|
puts "#{i}: #{part}"
|
||||||
i+=1
|
i += 1
|
||||||
end
|
end
|
||||||
print "Please choose partition to install to:"
|
print 'Please choose partition to install to:'
|
||||||
num=gets.chomp.to_i
|
num = gets.chomp.to_i
|
||||||
part=parts[num]
|
part = parts[num]
|
||||||
/(\w+)\d+/.match part
|
/(\w+)\d+/.match part
|
||||||
raw="/dev/#{$1}"
|
raw = "/dev/#{$1}"
|
||||||
elsif parts.length==0
|
elsif parts.length == 0
|
||||||
puts "No partitions detected."
|
puts 'No partitions detected.'
|
||||||
i=0
|
i = 0
|
||||||
for raw in raws
|
raws.each do |raw|
|
||||||
puts "#{i}: #{raw}"
|
puts "#{i}: #{raw}"
|
||||||
i+=1
|
i += 1
|
||||||
end
|
end
|
||||||
print "Please choose disk to install to:"
|
print 'Please choose disk to install to:'
|
||||||
num=gets.chomp.to_i
|
num = gets.chomp.to_i
|
||||||
raw=raws[num]
|
raw = raws[num]
|
||||||
print "Getting disk size..."
|
print 'Getting disk size...'
|
||||||
origsize=`sudo blockdev --getsize64 #{raw}`.chomp.to_i
|
origsize = `sudo blockdev --getsize64 #{raw}`.chomp.to_i
|
||||||
unit="MB"
|
unit = 'MB'
|
||||||
fullsize=(origsize/1024.to_f)/1024
|
fullsize = (origsize / 1024.to_f) / 1024
|
||||||
if fullsize%1024==0 or fullsize>2048
|
if (fullsize % 1024 == 0) || (fullsize > 2048)
|
||||||
fullsize=fullsize/1024.to_f
|
fullsize = fullsize / 1024.to_f
|
||||||
unit="GB"
|
unit = 'GB'
|
||||||
end
|
end
|
||||||
fullsize=fullsize.floor(1)
|
fullsize = fullsize.floor(1)
|
||||||
puts "#{fullsize}#{unit}"
|
puts "#{fullsize}#{unit}"
|
||||||
print "Partition size: (return for whole disk)"
|
print 'Partition size: (return for whole disk)'
|
||||||
size=gets.chomp.downcase
|
size = gets.chomp.downcase
|
||||||
if size.match /(\d)+m/ or size.match /(\d+)mb/
|
if size.match(/(\d)+m/)) || size.match(/(\d+)mb/))
|
||||||
size=(size.to_i)*1024*1024
|
size = size.to_i * 1024 * 1024
|
||||||
elsif size.match /(\d)+g/ or size.match /(\d+)gb/
|
elsif size.match(/(\d)+g/)) || size.match(/(\d+)gb/))
|
||||||
size=(size.to_i)*1024*1024*1024
|
size = size.to_i * 1024 * 1024 * 1024
|
||||||
elsif size==""
|
elsif size == ''
|
||||||
size=origsize
|
size = origsize
|
||||||
else
|
else
|
||||||
puts "Could not parse size. Aborting."
|
puts 'Could not parse size. Aborting.'
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
sfdisk_input="label: dos\n- #{size/1024}KiB L"
|
sfdisk_input = "label: dos\n- #{size / 1024}KiB L"
|
||||||
tmp=Tempfile.new("myosinstall")
|
tmp = Tempfile.new('myosinstall')
|
||||||
tmp.puts sfdisk_input
|
tmp.puts sfdisk_input
|
||||||
tmp.close
|
tmp.close
|
||||||
print "Partitioning..."
|
print 'Partitioning...'
|
||||||
`cat #{tmp.path} | sudo sfdisk #{raw} 2>/dev/null`
|
`cat #{tmp.path} | sudo sfdisk #{raw} 2>/dev/null`
|
||||||
puts "Done"
|
puts 'Done'
|
||||||
tmp.unlink
|
tmp.unlink
|
||||||
exit 1
|
exit 1
|
||||||
puts `sudo mkfs.ext2 #{raw}`
|
puts `sudo mkfs.ext2 #{raw}`
|
||||||
part="#{raw}1"
|
part = "#{raw}1"
|
||||||
raw="#{raw}"
|
raw = raw.to_s
|
||||||
else
|
else
|
||||||
part=parts[0]
|
part = parts[0]
|
||||||
/(\w+)\d+/.match parts[0]
|
/(\w+)\d+/.match parts[0]
|
||||||
raw="/dev/#{$1}"
|
raw = "/dev/#{$1}"
|
||||||
end
|
end
|
||||||
`mkdir -p usb`
|
`mkdir -p usb`
|
||||||
print "Mounting the disk..."
|
print 'Mounting the disk...'
|
||||||
`sudo mount #{part} usb`
|
`sudo mount #{part} usb`
|
||||||
puts "Done"
|
puts 'Done'
|
||||||
if !File.exists?("usb/boot")
|
if !File.exist?('usb/boot')
|
||||||
puts "Installing GRUB..."
|
puts 'Installing GRUB...'
|
||||||
`sudo grub-install --boot-directory=usb/boot #{raw}`
|
`sudo grub-install --boot-directory=usb/boot #{raw}`
|
||||||
end
|
end
|
||||||
print "Installing the OS..."
|
print 'Installing the OS...'
|
||||||
`sudo cp -r /vagrant/sysroot/* usb`
|
`sudo cp -r /vagrant/sysroot/* usb`
|
||||||
puts "Done"
|
puts 'Done'
|
||||||
print "Umounting disk..."
|
print 'Umounting disk...'
|
||||||
`sudo umount usb`
|
`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 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() {
|
void isr_install() {
|
||||||
idt_set_gate(0,(uint32_t)isr0);
|
idt_set_gate(0,(uint32_t)isr0);
|
||||||
idt_set_gate(1,(uint32_t)isr1);
|
idt_set_gate(1,(uint32_t)isr1);
|
||||||
@ -157,10 +161,6 @@ void isr_handler(registers_t* r) {
|
|||||||
char str[11];
|
char str[11];
|
||||||
int_to_ascii(tasking_get_PID(),str);
|
int_to_ascii(tasking_get_PID(),str);
|
||||||
serial_write_string(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) {
|
if (r->err_code==0) {
|
||||||
serial_write_string(", kernel process tried to read a non-present page entry at address ");
|
serial_write_string(", kernel process tried to read a non-present page entry at address ");
|
||||||
} else if (r->err_code==1) {
|
} else if (r->err_code==1) {
|
||||||
@ -181,12 +181,10 @@ void isr_handler(registers_t* r) {
|
|||||||
str[0]='\0';
|
str[0]='\0';
|
||||||
hex_to_ascii((unsigned int)addr,str);
|
hex_to_ascii((unsigned int)addr,str);
|
||||||
serial_write_string(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_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) {
|
// if ((r->err_code&1)==0) {
|
||||||
// // int dir_entry=(addr&0xFFC00000)>>22;
|
// // int dir_entry=(addr&0xFFC00000)>>22;
|
||||||
// // int table_entry=(addr&0x3FF000)>12;
|
// // int table_entry=(addr&0x3FF000)>12;
|
||||||
@ -298,10 +296,39 @@ void isr_handler(registers_t* r) {
|
|||||||
case SYSCALL_REGISTER_IRQ_HANDLER:
|
case SYSCALL_REGISTER_IRQ_HANDLER:
|
||||||
isr_register_handler((int)r->ebx,tasking_get_PID(),(void*)r->ecx);
|
isr_register_handler((int)r->ebx,tasking_get_PID(),(void*)r->ecx);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
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) {
|
if(info.pid==0) {
|
||||||
((isr_t)info.handler)(r);
|
((isr_t)info.handler)(r);
|
||||||
} else {
|
} 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 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 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_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.
|
* 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(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(MODEM_CMD_PORT(com),0x03); //Enable DTR and RTS
|
||||||
port_byte_out(INT_PORT(com),0x0); //Disable interrupts
|
port_byte_out(INT_PORT(com),0x0); //Disable interrupts
|
||||||
|
serial_printf("Port %d configured\n",com);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_init() {
|
void serial_init() {
|
||||||
@ -37,6 +39,10 @@ void serial_init() {
|
|||||||
if (port_byte_in(SCRATCH_PORT(0))==0xaa) {
|
if (port_byte_in(SCRATCH_PORT(0))==0xaa) {
|
||||||
configure(0,9600);
|
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) {
|
void serial_putc(char c) {
|
||||||
@ -45,3 +51,29 @@ void serial_putc(char c) {
|
|||||||
while(!IS_TRANSMIT_FIFO_EMPTY(0));
|
while(!IS_TRANSMIT_FIFO_EMPTY(0));
|
||||||
port_byte_out(DATA_PORT(0),c);
|
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) {
|
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();
|
size_t kstack_num=new_kstack();
|
||||||
if (kmode) {
|
if (kmode) {
|
||||||
size_t top_idx=(1024*(kstack_num+1));
|
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-=2;
|
||||||
user_stack[0]=param2;
|
user_stack[0]=param2;
|
||||||
user_stack[1]=param1;
|
user_stack[1]=param1;
|
||||||
|
/* serial_printf("User stack in address space: %x\n", user_stack); */
|
||||||
});
|
});
|
||||||
if (is_irq_handler) {
|
if (is_irq_handler) {
|
||||||
kstacks[top_idx-3]=(void*)task_init_no_int;
|
kstacks[top_idx-3]=(void*)task_init_no_int;
|
||||||
} else {
|
} else {
|
||||||
kstacks[top_idx-3]=(void*)task_init;
|
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-2]=(void*)user_stack;
|
||||||
kstacks[top_idx-1]=(void*)eip;
|
kstacks[top_idx-1]=(void*)eip;
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,31 @@
|
|||||||
void serial_init();
|
void serial_init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a character to the serial port
|
* Write a character to serial port 0
|
||||||
* \param c The character to write
|
* \param c The character to write
|
||||||
*/
|
*/
|
||||||
void serial_putc(char c);
|
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
|
* Write a string to the serial port
|
||||||
* \param s The string to write
|
* \param s The string to write
|
||||||
|
@ -116,15 +116,15 @@ void kmain(struct multiboot_boot_header_tag* hdr) {
|
|||||||
}
|
}
|
||||||
copy_data(address_space,ptr,pheader.memsz,(void*)pheader.vaddr);
|
copy_data(address_space,ptr,pheader.memsz,(void*)pheader.vaddr);
|
||||||
}
|
}
|
||||||
create_proc((void*)header.entry,address_space,NULL,NULL);
|
create_proc((void*)header.entry,address_space,NULL,NULL);
|
||||||
// for (int i=0;i<4;i++) {
|
for (int i=0;i<4;i++) {
|
||||||
// yield();
|
yield();
|
||||||
// }
|
}
|
||||||
// unblock_thread(1,0);
|
unblock_thread(1,0);
|
||||||
// for (int i=0;i<4;i++) {
|
for (int i=0;i<4;i++) {
|
||||||
// yield();
|
yield();
|
||||||
// }
|
}
|
||||||
// for (;;);
|
for (;;);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
109
kernel/tasking.c
109
kernel/tasking.c
@ -1,7 +1,3 @@
|
|||||||
/**
|
|
||||||
* \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cpu/halt.h"
|
#include "cpu/halt.h"
|
||||||
#include "cpu/paging.h"
|
#include "cpu/paging.h"
|
||||||
#include "cpu/serial.h"
|
#include "cpu/serial.h"
|
||||||
@ -10,6 +6,7 @@
|
|||||||
#include "tasking.h"
|
#include "tasking.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "rpc.h"
|
||||||
|
|
||||||
#define MAX_PROCS 32768 //!< Maximum number of processes that can be running at a time
|
#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
|
#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
|
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_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* 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
|
* Check whether a process is scheduled
|
||||||
* \param index The PID to check
|
* \param index The PID to check
|
||||||
* \return whether the process is scheduled
|
* \return whether the process is scheduled
|
||||||
*/
|
*/
|
||||||
static char is_proc_scheduled(pid_t index) {
|
static char is_proc_scheduled(pid_t index) {
|
||||||
size_t byte=index/8;
|
size_t byte=index/8;
|
||||||
size_t bit=index%8;
|
size_t bit=index%8;
|
||||||
@ -38,7 +36,7 @@ static char is_proc_scheduled(pid_t index) {
|
|||||||
/**
|
/**
|
||||||
* Mark a process as scheduled
|
* Mark a process as scheduled
|
||||||
* \param index The PID to mark
|
* \param index The PID to mark
|
||||||
*/
|
*/
|
||||||
static void mark_proc_scheduled(pid_t index) {
|
static void mark_proc_scheduled(pid_t index) {
|
||||||
if (is_proc_scheduled(index)) {
|
if (is_proc_scheduled(index)) {
|
||||||
serial_printf("Attempt to schedule a thread in a process with a scheduled thread! (PID %d)\n",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
|
* Unmark a process as scheduled
|
||||||
* \param index The PID to unmark
|
* \param index The PID to unmark
|
||||||
*/
|
*/
|
||||||
static void unmark_proc_scheduled(pid_t index) {
|
static void unmark_proc_scheduled(pid_t index) {
|
||||||
size_t byte=index/8;
|
size_t byte=index/8;
|
||||||
size_t bit=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
|
* Schedules a thread if the thread's prcess does not have a scheduled thread
|
||||||
* \param thread The thread to schedule
|
* \param thread The thread to schedule
|
||||||
*/
|
*/
|
||||||
void schedule_thread(Thread* thread) {
|
void schedule_thread(Thread* thread) {
|
||||||
if(!is_proc_scheduled(thread->process->pid)) {
|
if(!is_proc_scheduled(thread->process->pid)) {
|
||||||
if (ready_to_run_head) {
|
if (ready_to_run_head) {
|
||||||
@ -120,24 +118,24 @@ void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,v
|
|||||||
proc->first_thread=thread;
|
proc->first_thread=thread;
|
||||||
setup_kstack(thread,param1,param2,kmode,eip,is_irq_handler);
|
setup_kstack(thread,param1,param2,kmode,eip,is_irq_handler);
|
||||||
schedule_thread(thread);
|
schedule_thread(thread);
|
||||||
serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid);
|
/* serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid); */
|
||||||
serial_printf("Structure values:\n");
|
/* serial_printf("Structure values:\n"); */
|
||||||
serial_printf("kernel_esp=%x\n",thread->kernel_esp);
|
/* serial_printf("kernel_esp=%x\n",thread->kernel_esp); */
|
||||||
serial_printf("kernel_esp_top=%x\n",thread->kernel_esp_top);
|
/* serial_printf("kernel_esp_top=%x\n",thread->kernel_esp_top); */
|
||||||
serial_printf("address_space=%x\n",thread->address_space);
|
/* serial_printf("address_space=%x\n",thread->address_space); */
|
||||||
serial_printf("tid=%d\n",thread->tid);
|
/* serial_printf("tid=%d\n",thread->tid); */
|
||||||
serial_printf("state=%d\n",thread->state);
|
/* serial_printf("state=%d\n",thread->state); */
|
||||||
serial_printf("next_thread_in_process=%x\n",thread->next_thread_in_process);
|
/* 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("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("prev_ready_to_run=%x\n",thread->prev_ready_to_run); */
|
||||||
serial_printf("process=%x\n",thread->process);
|
/* serial_printf("process=%x\n",thread->process); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void tasking_init() {
|
void tasking_init() {
|
||||||
for (size_t i = 0; i < MAX_PROCS; i++) {
|
for (size_t i = 0; i < MAX_PROCS; i++) {
|
||||||
memset(&processes[i],0,sizeof(Process));
|
memset(&processes[i],0,sizeof(Process));
|
||||||
}
|
}
|
||||||
|
|
||||||
tasking_create_task(NULL,get_address_space(),1,NULL,NULL,0,0);
|
tasking_create_task(NULL,get_address_space(),1,NULL,NULL,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 The start thread
|
||||||
* \param thread_to_skip A thread to skip even if it's ready
|
* \param thread_to_skip A thread to skip even if it's ready
|
||||||
* \return the next ready thread
|
* \return the next ready thread
|
||||||
*/
|
*/
|
||||||
static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
#define HELPER \
|
#define HELPER \
|
||||||
while (thread&&(thread->state!=THREAD_READY||thread==thread_to_skip)) { \
|
while (thread&&(thread->state!=THREAD_READY||thread==thread_to_skip)) { \
|
||||||
thread=thread->next_thread_in_process; \
|
thread=thread->next_thread_in_process; \
|
||||||
}
|
}
|
||||||
//end define
|
//end define
|
||||||
#endif
|
#endif
|
||||||
Thread* start_of_list=thread->process->first_thread;
|
Thread* start_of_list=thread->process->first_thread;
|
||||||
thread=thread->next_thread_in_process;
|
thread=thread->next_thread_in_process;
|
||||||
HELPER;
|
HELPER;
|
||||||
@ -184,13 +182,13 @@ static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
|||||||
HELPER;
|
HELPER;
|
||||||
}
|
}
|
||||||
return thread;
|
return thread;
|
||||||
#undef HELPER
|
#undef HELPER
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch to a thread and schedule the next ready thread in the current process, if there is one.
|
* 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
|
* \param thread The thread to switch to
|
||||||
*/
|
*/
|
||||||
void switch_to_thread(Thread* thread) {
|
void switch_to_thread(Thread* thread) {
|
||||||
// Unlink the thread from the list of ready-to-run threads
|
// Unlink the thread from the list of ready-to-run threads
|
||||||
if (thread!=ready_to_run_head) {
|
if (thread!=ready_to_run_head) {
|
||||||
@ -220,13 +218,24 @@ void switch_to_thread(Thread* thread) {
|
|||||||
schedule_thread(current_thread_next_ready);
|
schedule_thread(current_thread_next_ready);
|
||||||
}
|
}
|
||||||
thread->state=THREAD_RUNNING;
|
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);
|
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() {
|
void tasking_yield() {
|
||||||
if (ready_to_run_head) {
|
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);
|
switch_to_thread(ready_to_run_head);
|
||||||
} else {
|
} else {
|
||||||
if (NUM_UNBLOCKED_THREADS(current_thread->process)>1) {
|
if (NUM_UNBLOCKED_THREADS(current_thread->process)>1) {
|
||||||
@ -244,11 +253,11 @@ void tasking_yield() {
|
|||||||
for(;;);
|
for(;;);
|
||||||
halt();
|
halt();
|
||||||
} else {
|
} 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.
|
// 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);
|
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);
|
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 pid The PID of the thread
|
||||||
* \param tid The TID of the thread
|
* \param tid The TID of the thread
|
||||||
* \return the thread wih the specified PID and TID
|
* \return the thread wih the specified PID and TID
|
||||||
*/
|
*/
|
||||||
static Thread* get_thread(pid_t pid,pid_t tid) {
|
static Thread* get_thread(pid_t pid,pid_t tid) {
|
||||||
if (processes[pid].num_threads==0) {
|
if (processes[pid].num_threads==0) {
|
||||||
serial_printf("PID %d does not exist!\n",pid);
|
serial_printf("PID %d does not exist!\n",pid);
|
||||||
@ -319,22 +328,22 @@ static Thread* get_thread(pid_t pid,pid_t tid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tasking_unblock(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);
|
Thread* thread=get_thread(pid,tid);
|
||||||
if (thread==NULL) {
|
if (thread==NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (thread->state==THREAD_EXITED||thread->state==THREAD_READY||thread->state==THREAD_RUNNING) {
|
if (thread->state==THREAD_EXITED||thread->state==THREAD_READY||thread->state==THREAD_RUNNING) {
|
||||||
serial_printf("Tried to unblock an exited/ready/running thread!\n");
|
serial_printf("Tried to unblock an exited/ready/running thread!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thread->state=THREAD_READY;
|
thread->state=THREAD_READY;
|
||||||
thread->process->num_threads_blocked--;
|
thread->process->num_threads_blocked--;
|
||||||
schedule_thread(thread);
|
schedule_thread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tasking_exit(int code) {
|
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)) {
|
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;
|
ready_to_run_head=ready_to_run_head->next_ready_to_run;
|
||||||
if (ready_to_run_head==NULL) {
|
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) {
|
for (Thread* thread=current_thread->process->first_thread;thread!=NULL;thread=thread->next_thread_in_process) {
|
||||||
if (thread->state!=THREAD_EXITED) {
|
if (thread->state!=THREAD_EXITED) {
|
||||||
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;
|
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() {
|
void tasking_thread_exit() {
|
||||||
|
serial_printf("PID %d TID %d is exiting\n",current_thread->process->pid,current_thread->tid);
|
||||||
tasking_block(THREAD_EXITED);
|
tasking_block(THREAD_EXITED);
|
||||||
|
thread_to_be_freed=current_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
char tasking_check_proc_exists(pid_t pid) {
|
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; \
|
int $80; \
|
||||||
"::"b"(str));
|
"::"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);
|
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
|
#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[]) {
|
char* const argv[], char* const envp[]) {
|
||||||
FILE* image=fopen((char*)path,"r");
|
FILE* image=fopen((char*)path,"r");
|
||||||
elf_header header;
|
elf_header header;
|
||||||
|
serial_print("Read magic number\n");
|
||||||
fread(&header,sizeof(elf_header),1,image);
|
fread(&header,sizeof(elf_header),1,image);
|
||||||
if (header.magic!=ELF_MAGIC) {
|
if (header.magic!=ELF_MAGIC) {
|
||||||
serial_print("Bad magic number (");
|
serial_print("Bad magic number (");
|
||||||
|
134
libc/stdio.c
134
libc/stdio.c
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <serdes.h>
|
#include <serdes.h>
|
||||||
@ -17,7 +17,7 @@ FILE* stderr=NULL; //!< Standard error
|
|||||||
/**
|
/**
|
||||||
* Initialize stdio.
|
* Initialize stdio.
|
||||||
* Must not be called by user code.
|
* Must not be called by user code.
|
||||||
*/
|
*/
|
||||||
void __stdio_init() {
|
void __stdio_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ FILE* fopen(char* filename,char* mode) {
|
|||||||
* \param c The character to write
|
* \param c The character to write
|
||||||
* \param stream The stream to write to
|
* \param stream The stream to write to
|
||||||
* \returns the written character, or EOF on failure
|
* \returns the written character, or EOF on failure
|
||||||
*/
|
*/
|
||||||
int putc(int c, FILE* stream) __attribute__ ((alias ("fputc")));
|
int putc(int c, FILE* stream) __attribute__ ((alias ("fputc")));
|
||||||
|
|
||||||
int fputc(int c, FILE* stream) {
|
int fputc(int c, FILE* stream) {
|
||||||
@ -64,7 +64,7 @@ int fputc(int c, FILE* stream) {
|
|||||||
* Gets a character from a file
|
* Gets a character from a file
|
||||||
* \param stream The file to read from
|
* \param stream The file to read from
|
||||||
* \returns the read character, or EOF if the read fails
|
* \returns the read character, or EOF if the read fails
|
||||||
*/
|
*/
|
||||||
int getc(FILE* stream) __attribute__ ((alias ("fgetc")));
|
int getc(FILE* stream) __attribute__ ((alias ("fgetc")));
|
||||||
|
|
||||||
int fgetc(FILE* stream) {
|
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) {
|
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};
|
serdes_state state={0};
|
||||||
serialize_ptr(stream->fs_data,&state);
|
serialize_ptr(stream->fs_data,&state);
|
||||||
serialize_int(size*count,&state);
|
serialize_int(size*count,&state);
|
||||||
@ -173,61 +175,61 @@ int mount(char* file,char* type,char* path) {
|
|||||||
|
|
||||||
int vfprintf(FILE* stream,const char* format,va_list arg) {
|
int vfprintf(FILE* stream,const char* format,va_list arg) {
|
||||||
int c;
|
int c;
|
||||||
for(;*format!='\0';format++) {
|
for(;*format!='\0';format++) {
|
||||||
if(*format!='%') {
|
if(*format!='%') {
|
||||||
c=fputc(*format,stream);
|
c=fputc(*format,stream);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
format++;
|
format++;
|
||||||
switch(*format) {
|
switch(*format) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
int i=va_arg(arg,int);
|
int i=va_arg(arg,int);
|
||||||
c=fputc(i,stream);
|
c=fputc(i,stream);
|
||||||
if (c==EOF) {
|
if (c==EOF) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd': {
|
case 'd': {
|
||||||
int i=va_arg(arg,int); //Fetch Decimal/Integer argument
|
int i=va_arg(arg,int); //Fetch Decimal/Integer argument
|
||||||
if(i<0) {
|
if(i<0) {
|
||||||
i=-i;
|
i=-i;
|
||||||
fputc('-',stream);
|
fputc('-',stream);
|
||||||
}
|
}
|
||||||
char str[11];
|
char str[11];
|
||||||
int_to_ascii(i,str);
|
int_to_ascii(i,str);
|
||||||
c=fputs(str,stream);
|
c=fputs(str,stream);
|
||||||
if (c==EOF) {
|
if (c==EOF) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// case 'o': {
|
// case 'o': {
|
||||||
// int i=va_arg(arg,unsigned int); //Fetch Octal representation
|
// int i=va_arg(arg,unsigned int); //Fetch Octal representation
|
||||||
// puts(convert(i,8));
|
// puts(convert(i,8));
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
case 's': {
|
case 's': {
|
||||||
char* s=va_arg(arg,char*);
|
char* s=va_arg(arg,char*);
|
||||||
c=fputs(s,stream);
|
c=fputs(s,stream);
|
||||||
if (c==EOF) {
|
if (c==EOF) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': {
|
case 'x': {
|
||||||
unsigned int i=va_arg(arg, unsigned int);
|
unsigned int i=va_arg(arg, unsigned int);
|
||||||
char str[11];
|
char str[11];
|
||||||
str[0]='\0';
|
str[0]='\0';
|
||||||
hex_to_ascii(i,str);
|
hex_to_ascii(i,str);
|
||||||
c=fputs(str,stream);
|
c=fputs(str,stream);
|
||||||
if (c==EOF) {
|
if (c==EOF) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,16 +261,16 @@ int printf(const char* format,...) {
|
|||||||
|
|
||||||
int fseek(FILE* stream,long offset,int origin) {
|
int fseek(FILE* stream,long offset,int origin) {
|
||||||
switch (origin) {
|
switch (origin) {
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
stream->pos=offset;
|
stream->pos=offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
stream->pos+=offset;
|
stream->pos+=offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,10 @@
|
|||||||
#define SYSCALL_RPC_IS_INIT 22
|
#define SYSCALL_RPC_IS_INIT 22
|
||||||
#define SYSCALL_REGISTER_IRQ_HANDLER 23
|
#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
|
#endif
|
||||||
|
105
network.rb
105
network.rb
@ -1,65 +1,64 @@
|
|||||||
require "socket"
|
# frozen_string_literal: true
|
||||||
s=TCPServer.new("localhost",3000)
|
|
||||||
c=s.accept
|
require 'socket'
|
||||||
udpsocks=[]
|
s = TCPServer.new('localhost', 3000)
|
||||||
tcpsocks=[]
|
c = s.accept
|
||||||
next_sock=0
|
udpsocks = []
|
||||||
puts "Connection established"
|
tcpsocks = []
|
||||||
while true
|
next_sock = 0
|
||||||
ch=c.getc
|
puts 'Connection established'
|
||||||
if ch==nil
|
loop do
|
||||||
next
|
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
|
end
|
||||||
cmd=ch.ord
|
if cmd == 4
|
||||||
if cmd==0
|
info = c.read(12).unpack('L<CCCCS<S<')
|
||||||
c.print [192,168,0,10].pack("CCCC")
|
msg = c.read(info[6])
|
||||||
|
udpsocks[info[0]].send(msg, 0, "#{info[1]}.#{info[2]}.#{info[3]}.#{info[4]}", info[5])
|
||||||
end
|
end
|
||||||
if cmd==1
|
if cmd == 5
|
||||||
sock=UDPSocket.new()
|
id = c.read(4).unpack1('L<')
|
||||||
sock.bind("10.0.0.180",0)
|
msg = udpsocks[id].recv(65_536)
|
||||||
c.print [next_sock,sock.addr[1]].pack("L<L<")
|
if msg == ''
|
||||||
udpsocks[next_sock]=sock
|
c.print [0].pack('L<')
|
||||||
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<")
|
|
||||||
else
|
else
|
||||||
c.print [msg.length].pack("L<")
|
c.print [msg.length].pack('L<')
|
||||||
c.print msg
|
c.print msg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if cmd==6
|
if cmd == 6
|
||||||
id=c.read(4).unpack("L<")[0]
|
id = c.read(4).unpack1('L<')
|
||||||
udpsocks[id]=nil
|
udpsocks[id] = nil
|
||||||
end
|
end
|
||||||
if cmd==7
|
if cmd == 7
|
||||||
info=c.read(6).unpack("CCCCS<")
|
info = c.read(6).unpack('CCCCS<')
|
||||||
sock=TCPSocket.new("#{info[0]}.#{info[1]}.#{info[2]}.#{info[3]}",info[4])
|
sock = TCPSocket.new("#{info[0]}.#{info[1]}.#{info[2]}.#{info[3]}", info[4])
|
||||||
c.print [next_sock].pack("L<")
|
c.print [next_sock].pack('L<')
|
||||||
tcpsocks[next_sock]=sock
|
tcpsocks[next_sock] = sock
|
||||||
next_sock+=1;
|
next_sock += 1
|
||||||
end
|
end
|
||||||
if cmd==8
|
if cmd == 8
|
||||||
info=c.read(6).unpack("L<S<")
|
info = c.read(6).unpack('L<S<')
|
||||||
msg=c.read(info[1])
|
msg = c.read(info[1])
|
||||||
tcpsocks[info[0]].print msg
|
tcpsocks[info[0]].print msg
|
||||||
end
|
end
|
||||||
if cmd==9
|
next unless cmd == 9
|
||||||
id=c.read(4).unpack("L<")[0]
|
|
||||||
if !tcpsocks[id].ready? and tcpsocks[id].closed?
|
id = c.read(4).unpack1('L<')
|
||||||
c.print [0].pack("L<")
|
if !tcpsocks[id].ready? && tcpsocks[id].closed?
|
||||||
else
|
c.print [0].pack('L<')
|
||||||
msg=tcpsocks[id].gets
|
else
|
||||||
c.print [msg.length].pack("L<")
|
msg = tcpsocks[id].gets
|
||||||
c.print msg
|
c.print [msg.length].pack('L<')
|
||||||
end
|
c.print msg
|
||||||
end
|
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;
|
fs_type* fs_type_list=NULL;
|
||||||
|
|
||||||
void vfs_mount(void* args) {
|
void vfs_mount(void* args) {
|
||||||
|
serial_print("MOUNT\n");
|
||||||
serdes_state state;
|
serdes_state state;
|
||||||
start_deserialize(args,&state);
|
start_deserialize(args,&state);
|
||||||
char* type=deserialize_str(&state);
|
char* type=deserialize_str(&state);
|
||||||
char* dev=deserialize_str(&state);
|
char* dev=deserialize_str(&state);
|
||||||
char* mount_path=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);
|
rpc_deallocate_buf(args,state.sizeorpos);
|
||||||
fs_type* fstype=fs_type_list;
|
fs_type* fstype=fs_type_list;
|
||||||
pid_t fs_pid=0;
|
pid_t fs_pid=0;
|
||||||
@ -46,6 +53,7 @@ void vfs_mount(void* args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fs_pid) {
|
if (!fs_pid) {
|
||||||
|
serial_print("NO FS PID\n");
|
||||||
int err=1;
|
int err=1;
|
||||||
rpc_return(&err,sizeof(int));
|
rpc_return(&err,sizeof(int));
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
@ -58,6 +66,7 @@ void vfs_mount(void* args) {
|
|||||||
int* errbuf=malloc(sizeof(int));
|
int* errbuf=malloc(sizeof(int));
|
||||||
*errbuf=err;
|
*errbuf=err;
|
||||||
if (err) {
|
if (err) {
|
||||||
|
serial_print("MOUNT ERROR\n");
|
||||||
rpc_return(errbuf,sizeof(int));
|
rpc_return(errbuf,sizeof(int));
|
||||||
free(errbuf);
|
free(errbuf);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
@ -74,10 +83,13 @@ void vfs_mount(void* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vfs_register_fs(void* args) {
|
void vfs_register_fs(void* args) {
|
||||||
|
serial_print("REGISTER FS\n");
|
||||||
serdes_state state;
|
serdes_state state;
|
||||||
start_deserialize(args,&state);
|
start_deserialize(args,&state);
|
||||||
char* name=deserialize_str(&state);
|
char* name=deserialize_str(&state);
|
||||||
pid_t pid=deserialize_int(&state);
|
pid_t pid=deserialize_int(&state);
|
||||||
|
serial_print(name);
|
||||||
|
serial_print("\n");
|
||||||
fs_type* type=malloc(sizeof(fs_type));
|
fs_type* type=malloc(sizeof(fs_type));
|
||||||
rpc_deallocate_buf(args,state.sizeorpos);
|
rpc_deallocate_buf(args,state.sizeorpos);
|
||||||
type->name=name;
|
type->name=name;
|
||||||
@ -89,9 +101,12 @@ void vfs_register_fs(void* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void open(void* args) {
|
void open(void* args) {
|
||||||
|
serial_print("OPEN\n");
|
||||||
serdes_state state;
|
serdes_state state;
|
||||||
start_deserialize(args,&state);
|
start_deserialize(args,&state);
|
||||||
char* path=deserialize_str(&state);
|
char* path=deserialize_str(&state);
|
||||||
|
serial_print(path);
|
||||||
|
serial_print("\n");
|
||||||
rpc_deallocate_buf(args,state.sizeorpos);
|
rpc_deallocate_buf(args,state.sizeorpos);
|
||||||
mount_point* mnt=mount_point_list;
|
mount_point* mnt=mount_point_list;
|
||||||
mount_point* mnt_pnt=NULL;
|
mount_point* mnt_pnt=NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user