大更新
This commit is contained in:
parent
4ed9674bde
commit
49f205ea9d
10
apps/Makefile
Normal file
10
apps/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
default: Makefile
|
||||
make -r -C libs
|
||||
make -r -C init
|
||||
make -r -C base_service
|
||||
|
||||
clean:
|
||||
rm ../isodir/apps/*
|
||||
make -r -C libs clean
|
||||
make -r -C init clean
|
||||
make -r -C base_service clean
|
14
apps/base_service/Makefile
Normal file
14
apps/base_service/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
OBJS_PACK = out/service.obj
|
||||
include ../def.mk
|
||||
|
||||
default: $(OBJS_PACK)
|
||||
$(LINK) $(OBJS_PACK) $(BASIC_LIB_C) -o ../../isodir/apps/service.bin
|
||||
out/%.obj : %.c Makefile
|
||||
$(C) -c $*.c -o out/$*.obj
|
||||
out/%.obj : %.cpp Makefile
|
||||
$(CPP) -c $*.cpp -o out/$*.obj
|
||||
out/%.obj : %.asm Makefile
|
||||
nasm -f elf $*.asm -o out/$*.obj
|
||||
|
||||
clean:
|
||||
rm out/*
|
7
apps/base_service/service.c
Normal file
7
apps/base_service/service.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "../include/stdio.h"
|
||||
|
||||
int main(){
|
||||
while (1);
|
||||
put_char('A');
|
||||
return 0;
|
||||
}
|
16
apps/def.mk
Normal file
16
apps/def.mk
Normal file
@ -0,0 +1,16 @@
|
||||
CFLAGS = -m32 -I$(INCLUDE_PATH) -nostdinc -nolibc -nostdlib -ffreestanding -fno-stack-protector -Qn -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fomit-frame-pointer -finput-charset=UTF-8 -fexec-charset=GB2312 -march=pentium -Qn -O0 -w
|
||||
CPPFLAGS = -m32 -I$(INCLUDE_PATH) -nostdinc -nolibc -nostdlib -ffreestanding -fno-exceptions -fno-stack-protector -Qn -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fomit-frame-pointer -finput-charset=UTF-8 -fexec-charset=GB2312 -Qn -O3 -march=pentium -fno-rtti -w
|
||||
|
||||
CC = gcc
|
||||
|
||||
C = $(CC) $(CFLAGS)
|
||||
CPP = $(CC) $(CPPFLAGS)
|
||||
INCLUDE_PATH := ../include
|
||||
NASM = nasm
|
||||
LIBS_PATH := ../libo
|
||||
|
||||
LD = ld
|
||||
LD_FLAGS = -Ttext 0xb0000010 -m elf_i386 -static -e main
|
||||
LINK = $(LD) $(LD_FLAGS)
|
||||
|
||||
BASIC_LIB_C = $(LIBS_PATH)/libp.a
|
6
apps/include/stdio.h
Normal file
6
apps/include/stdio.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef CRASHPOWEROS_STDIO_H
|
||||
#define CRASHPOWEROS_STDIO_H
|
||||
|
||||
void put_char(char c);
|
||||
|
||||
#endif
|
14
apps/init/Makefile
Normal file
14
apps/init/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
OBJS_PACK = out/init.obj
|
||||
include ../def.mk
|
||||
|
||||
default: $(OBJS_PACK)
|
||||
$(LINK) $(OBJS_PACK) $(BASIC_LIB_C) -o ../../isodir/apps/init.bin
|
||||
out/%.obj : %.c Makefile
|
||||
$(C) -c $*.c -o out/$*.obj
|
||||
out/%.obj : %.cpp Makefile
|
||||
$(CPP) -c $*.cpp -o out/$*.obj
|
||||
out/%.obj : %.asm Makefile
|
||||
nasm -f elf $*.asm -o out/$*.obj
|
||||
|
||||
clean:
|
||||
rm out/*
|
7
apps/init/init.c
Normal file
7
apps/init/init.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "../include/stdio.h"
|
||||
|
||||
int main(){
|
||||
while (1);
|
||||
put_char('A');
|
||||
return 0;
|
||||
}
|
14
apps/libs/Makefile
Normal file
14
apps/libs/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
OBJS_PACK = out/syscall.obj
|
||||
|
||||
|
||||
default : $(OBJS_PACK)
|
||||
ar rv ../libo/libp.a $(OBJS_PACK)
|
||||
out/%.obj : %.c Makefile
|
||||
gcc -m32 -I../include -nostdinc -nostdlib -fno-builtin -ffreestanding -fno-stack-protector -Qn -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fomit-frame-pointer -march=pentium -O0 -w -c $*.c -o out/$*.obj
|
||||
out/%.obj : %.cpp Makefile
|
||||
gcc -m32 -I../include -nostdinc -nostdlib -fno-builtin -ffreestanding -fno-stack-protector -Qn -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fomit-frame-pointer -march=pentium -O0 -w -c $*.cpp -o out/$*.obj
|
||||
out/%.obj : %.asm Makefile
|
||||
nasm -f elf $*.asm -o out/$*.obj
|
||||
clean:
|
||||
rm out/*
|
||||
rm ../libo/*
|
11
apps/libs/syscall.asm
Normal file
11
apps/libs/syscall.asm
Normal file
@ -0,0 +1,11 @@
|
||||
global put_char
|
||||
|
||||
put_char:
|
||||
push edx
|
||||
push eax
|
||||
mov edx,[ss:esp+12]
|
||||
mov eax,0x01
|
||||
int 80h
|
||||
pop eax
|
||||
pop edx
|
||||
ret
|
12
bochsrc.txt
Normal file
12
bochsrc.txt
Normal file
@ -0,0 +1,12 @@
|
||||
megs: 2048
|
||||
vga: extension=vbe, update_freq=15
|
||||
|
||||
ata1-master: type=cdrom, path=cpos.iso, status=inserted
|
||||
#ata0-master: type=disk, path=disk.img, mode=flat, cylinders=2, heads=16, spt=63
|
||||
ata2: enabled=false
|
||||
ata3: enabled=false
|
||||
boot: cdrom
|
||||
|
||||
display_library: win32, options="gui_debug"
|
||||
|
||||
#vgaromimage: file=/usr/share/vgabios/vgabios.bin
|
4
build.py
4
build.py
@ -89,7 +89,7 @@ def build_kernel(): # 构建内核本体
|
||||
def build_data(): # 构建常用工具
|
||||
print("Building util source code...")
|
||||
for file in os.listdir(cd + dir_ + src + 'util'):
|
||||
cmd = cd + gcc + "-O2 " + src + "util" + dir_ + file + " -o " + "target" + dir_ + file.split(".")[0] + ".o"
|
||||
cmd = cd + gcc + "-O0 " + src + "util" + dir_ + file + " -o " + "target" + dir_ + file.split(".")[0] + ".o"
|
||||
e = os.system(cmd)
|
||||
if e != 0:
|
||||
return -1
|
||||
@ -132,7 +132,7 @@ def linker(): # 交叉编译链接
|
||||
for file in os.listdir(cd + dir_ + 'target'):
|
||||
source_file = source_file + " target" + dir_ + file
|
||||
return os.system(
|
||||
cd + "/i686_elf_tools/bin/i686-elf-g++.exe -T linker.ld -o isodir" + dir_ + "sys" + dir_ + "kernel.elf -ffreestanding -O2 -nostdlib " + source_file + " -lgcc")
|
||||
cd + "/i686_elf_tools/bin/i686-elf-g++.exe -T linker.ld -o isodir" + dir_ + "sys" + dir_ + "kernel.elf -ffreestanding -nostdlib " + source_file + " -lgcc")
|
||||
|
||||
|
||||
def launch():
|
||||
|
@ -34,3 +34,4 @@ longjmp:
|
||||
.1: ; let longjmp's ret addr as setjmp's ret addr
|
||||
mov [esp + 0], ecx ; ret addr = ecx = setjmp's next code
|
||||
ret
|
||||
|
||||
|
@ -56,10 +56,8 @@ int acpi_enable() {
|
||||
}
|
||||
// check enable status
|
||||
if (i < 300) {
|
||||
printf("[acpi]: Enable ACPI\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("Counld't enable ACPI\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -89,10 +87,8 @@ int acpi_disable() {
|
||||
}
|
||||
|
||||
if (i < 300) {
|
||||
printf("ACPI Disable!\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("Could't disable ACPI\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -140,7 +136,6 @@ void power_off() {
|
||||
if (!SCI_EN)
|
||||
return;
|
||||
while (1) {
|
||||
printf("[acpi] send power off command!\n");
|
||||
io_out16((uint32_t) PM1a_CNT, SLP_TYPa | SLP_EN);
|
||||
if (!PM1b_CNT) {
|
||||
io_out16((uint32_t) PM1b_CNT, SLP_TYPb | SLP_EN);
|
||||
@ -180,17 +175,12 @@ static void AcpiPowerInit() {
|
||||
if (PM1b_ENABLE_REG == len)
|
||||
PM1b_ENABLE_REG = 0;
|
||||
|
||||
printf("[acpi]: Setting Power event listener...\n");
|
||||
|
||||
io_out16(PM1a_ENABLE_REG, (1 << 8));
|
||||
if (PM1b_ENABLE_REG) {
|
||||
io_out16((uint16_t)
|
||||
PM1b_ENABLE_REG, (uint8_t)(1 << 8));
|
||||
}
|
||||
|
||||
printf("ACPI : SCI_INT %08x\n", (uint8_t)
|
||||
facp->SCI_INT);
|
||||
|
||||
register_interrupt_handler(facp->SCI_INT, AcpiPowerHandler);
|
||||
}
|
||||
|
||||
@ -217,7 +207,6 @@ uint8_t *AcpiCheckRSDPtr(void *ptr) {
|
||||
|
||||
// check signature
|
||||
if (!memcmp(sign, bptr, 8)) {
|
||||
printf("[acpi] rsdp found at %0x\n", bptr);
|
||||
rsdp_address = bptr;
|
||||
for (i = 0; i < sizeof(acpi_rsdptr_t); i++) {
|
||||
check += *bptr;
|
||||
@ -255,7 +244,7 @@ static int AcpiSysInit() {
|
||||
rsdt = (acpi_rsdt_t *) AcpiGetRSDPtr();
|
||||
if (!rsdt || AcpiCheckHeader(rsdt, "RSDT") < 0) {
|
||||
printf("No ACPI\n");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
entrys = rsdt->length - HEADER_SIZE / 4;
|
||||
@ -315,7 +304,7 @@ static int AcpiSysInit() {
|
||||
} else {
|
||||
printf("[acpi] no found DSDT table\n");
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
@ -323,9 +312,8 @@ static int AcpiSysInit() {
|
||||
}
|
||||
|
||||
void acpi_install() {
|
||||
AcpiSysInit();
|
||||
klogf(AcpiSysInit(),"Load acpi driver.\n");
|
||||
acpi_enable_flag = !acpi_enable();
|
||||
// power init
|
||||
hpet_initialize();
|
||||
AcpiPowerInit();
|
||||
}
|
||||
@ -383,14 +371,10 @@ void hpet_initialize() {
|
||||
printf("can not found acpi hpet table\n");
|
||||
}
|
||||
|
||||
printf("[acpi-hpet]: OEM: %s | Version: %d\n",hpet->oem,hpet->oemVersion);
|
||||
|
||||
hpetInfo = (HpetInfo *) hpet->hpetAddress.address;
|
||||
|
||||
uint32_t counterClockPeriod = hpetInfo->generalCapabilities >> 32;
|
||||
hpetPeriod = counterClockPeriod / 1000000;
|
||||
|
||||
hpetInfo->generalConfiguration |= 1; // 启用hpet
|
||||
|
||||
printf("[acpi]: hpet successfully enabled.\n");
|
||||
}
|
@ -68,7 +68,6 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
// 2- Disable IRQs:
|
||||
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
||||
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
||||
logk("w1\n");
|
||||
// 3- Detect ATA-ATAPI Devices:
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++) {
|
||||
@ -78,20 +77,15 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
// (I) Select Drive:
|
||||
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
|
||||
sleep(1); // Wait 1ms for drive select to work.
|
||||
logk("I\n");
|
||||
// (II) Send ATA Identify Command:
|
||||
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
sleep(1); // This function should be implemented in your OS. which waits
|
||||
// for 1 ms. it is based on System Timer Device Driver.
|
||||
logk("II\n");
|
||||
// (III) Polling:
|
||||
if (ide_read(i, ATA_REG_STATUS) == 0)
|
||||
continue; // If Status = 0, No Device.
|
||||
logk("III\n");
|
||||
while (1) {
|
||||
logk("read ide....\n");
|
||||
status = ide_read(i, ATA_REG_STATUS);
|
||||
logk("read ok\n");
|
||||
if ((status & ATA_SR_ERR)) {
|
||||
err = 1;
|
||||
break;
|
||||
@ -101,7 +95,6 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
}
|
||||
|
||||
// (IV) Probe for ATAPI Devices:
|
||||
logk("IV\n");
|
||||
if (err != 0) {
|
||||
unsigned char cl = ide_read(i, ATA_REG_LBA1);
|
||||
unsigned char ch = ide_read(i, ATA_REG_LBA2);
|
||||
@ -118,11 +111,9 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
}
|
||||
|
||||
// (V) Read Identification Space of the Device:
|
||||
logk("V\n");
|
||||
ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128);
|
||||
|
||||
// (VI) Read Device Parameters:
|
||||
logk("VI\n");
|
||||
ide_devices[count].Reserved = 1;
|
||||
ide_devices[count].Type = type;
|
||||
ide_devices[count].Channel = i;
|
||||
@ -135,7 +126,6 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
*((unsigned int *) (ide_buf + ATA_IDENT_COMMANDSETS));
|
||||
|
||||
// (VII) Get Size:
|
||||
logk("VII\n");
|
||||
if (ide_devices[count].CommandSets & (1 << 26))
|
||||
// Device uses 48-Bit Addressing:
|
||||
ide_devices[count].Size =
|
||||
@ -147,7 +137,6 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
|
||||
// (VIII) String indicates model of device (like Western Digital HDD and
|
||||
// SONY DVD-RW...):
|
||||
logk("VIII\n");
|
||||
for (k = 0; k < 40; k += 2) {
|
||||
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
|
||||
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
|
||||
@ -161,10 +150,12 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
vdisk vd;
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (ide_devices[i].Reserved == 1) {
|
||||
/*
|
||||
logkf(" %d Found %s Drive %dMB - %s\n", i,
|
||||
(const char *[]) {"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */
|
||||
ide_devices[i].Size / 1024 / 2, /* Size */
|
||||
(const char *[]) {"ATA", "ATAPI"}[ide_devices[i].Type],
|
||||
ide_devices[i].Size / 1024 / 2,
|
||||
ide_devices[i].Model);
|
||||
*/
|
||||
strcpy(vd.DriveName, ide_devices[i].Model);
|
||||
if(ide_devices[i].Type == IDE_ATAPI) {
|
||||
vd.flag = 2;
|
||||
@ -175,7 +166,7 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
vd.Read = Read;
|
||||
vd.Write = Write;
|
||||
vd.size = ide_devices[i].Size;
|
||||
printf("[Disk-(%c)]: Size: %dMB | %s | Name: %s\n", register_vdisk(vd), vd.size,(const char *[]) {"ATA", "ATAPI"}[ide_devices[i].Type], vd.DriveName);
|
||||
klogf(true,"Disk-(%c) Size: %dMB | %s | Name: %s\n", register_vdisk(vd), vd.size,(const char *[]) {"ATA", "ATAPI"}[ide_devices[i].Type], vd.DriveName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,21 +233,17 @@ unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
|
||||
|
||||
// (II) Wait for BSY to be cleared:
|
||||
// -------------------------------------------------
|
||||
logk("II\n");
|
||||
int a = ide_read(channel, ATA_REG_STATUS);
|
||||
while (a & ATA_SR_BSY) {
|
||||
logkf("a=%d\n", a & ATA_SR_BSY); // Wait for BSY to be zero.
|
||||
a = ide_read(channel, ATA_REG_STATUS);
|
||||
sleep(1);
|
||||
}
|
||||
logk("II OK\n");
|
||||
if (advanced_check) {
|
||||
unsigned char state =
|
||||
ide_read(channel, ATA_REG_STATUS); // Read Status Register.
|
||||
|
||||
// (III) Check For Errors:
|
||||
// -------------------------------------------------
|
||||
logk("III\n");
|
||||
if (state & ATA_SR_ERR)
|
||||
return 2; // Error.
|
||||
|
||||
@ -356,7 +343,6 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
ide_write(channel, ATA_REG_CONTROL,
|
||||
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
|
||||
// (I) Select one from LBA28, LBA48 or CHS;
|
||||
logkf("I %02x\n", channels[channel].nIEN);
|
||||
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or
|
||||
// you are giving a wrong LBA.
|
||||
// LBA48:
|
||||
@ -393,14 +379,11 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
(63); // Head number is written to HDDEVSEL lower 4-bits.
|
||||
}
|
||||
// (II) See if drive supports DMA or not;
|
||||
logk("II\n");
|
||||
dma = 0; // We don't support DMA
|
||||
// (III) Wait if the drive is busy;
|
||||
logk("III\n");
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {
|
||||
} // Wait if busy.
|
||||
// (IV) Select Drive from the controller;
|
||||
logk("IV\n");
|
||||
if (lba_mode == 0)
|
||||
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||
0xA0 | (slavebit << 4) | head); // Drive & CHS.
|
||||
@ -443,7 +426,6 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
if (lba_mode == 2 && dma == 1 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_DMA_EXT;
|
||||
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
|
||||
logk("IV1\n");
|
||||
if (dma)
|
||||
if (direction == 0);
|
||||
// DMA Read.
|
||||
@ -457,7 +439,6 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
if (err = ide_polling(channel, 1))
|
||||
return err; // Polling, set error and exit if there is.
|
||||
|
||||
logkf("words=%d bus=%d\n", words, bus);
|
||||
for (int h = 0; h < words; h++) {
|
||||
unsigned short a = io_in16(bus);
|
||||
word_[i * words + h] = a;
|
||||
@ -489,21 +470,17 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
}
|
||||
|
||||
void ide_wait_irq() {
|
||||
logk("WAITING\n");
|
||||
while (!ide_irq_invoked);
|
||||
ide_irq_invoked = 0;
|
||||
logk("IDE_WAIT_IRQ!\n");
|
||||
}
|
||||
|
||||
void ide_irq() {
|
||||
logk("ide irq.\n");
|
||||
ide_irq_invoked = 1;
|
||||
}
|
||||
|
||||
unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||
unsigned char numsects, unsigned short selector,
|
||||
unsigned int edi) {
|
||||
logk("cdrom read.\n");
|
||||
unsigned int channel = ide_devices[drive].Channel;
|
||||
unsigned int slavebit = ide_devices[drive].Drive;
|
||||
unsigned int bus = channels[channel].base;
|
||||
@ -516,7 +493,6 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||
channels[channel].nIEN = ide_irq_invoked = 0x0);
|
||||
// (I): Setup SCSI Packet:
|
||||
// ------------------------------------------------------------------
|
||||
logk("CDROM I\n");
|
||||
atapi_packet[0] = ATAPI_CMD_READ;
|
||||
atapi_packet[1] = 0x0;
|
||||
atapi_packet[2] = (lba >> 24) & 0xFF;
|
||||
@ -531,12 +507,9 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||
atapi_packet[11] = 0x0; // (II): Select the drive:
|
||||
// ------------------------------------------------------------------
|
||||
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
|
||||
logk("CDROM II\n");
|
||||
// (III): Delay 400 nanoseconds for select to complete:
|
||||
for (int i = 0; i < 4000; i++);
|
||||
logk("CDROM III\n");
|
||||
// ------------------------------------------------------------------
|
||||
logk("CDROM IV\n");
|
||||
for (int i = 0; i < 4; i++)
|
||||
ide_read(channel,
|
||||
ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes
|
||||
@ -547,7 +520,6 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||
0); // PIO mode.
|
||||
// (V): Tell the Controller the size of buffer:
|
||||
// ------------------------------------------------------------------
|
||||
logk("CDROM V\n");
|
||||
ide_write(channel, ATA_REG_LBA1,
|
||||
(words * 2) & 0xFF); // Lower Byte of Sector Size.
|
||||
ide_write(channel, ATA_REG_LBA2,
|
||||
@ -563,20 +535,17 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba,
|
||||
|
||||
// (VIII): Sending the packet data:
|
||||
// ------------------------------------------------------------------
|
||||
logk("CDROM VIII\n");
|
||||
uint16_t *_atapi_packet = atapi_packet;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
io_out16(bus, _atapi_packet[i]);
|
||||
}
|
||||
// (IX): Receiving Data:
|
||||
// ------------------------------------------------------------------
|
||||
logk("CDROM IX\n");
|
||||
uint16_t *_word = edi;
|
||||
for (i = 0; i < numsects; i++) {
|
||||
ide_wait_irq(); // Wait for an IRQ.
|
||||
if (err = ide_polling(channel, 1))
|
||||
return err; // Polling and return if error.
|
||||
logkf("CDROM words = %d\n", words);
|
||||
|
||||
insl(bus, _word + i * words, words / 2);
|
||||
}
|
||||
@ -609,7 +578,6 @@ void ide_read_sectors(unsigned char drive, unsigned char numsects,
|
||||
else {
|
||||
unsigned char err;
|
||||
if (ide_devices[drive].Type == IDE_ATA) {
|
||||
logk("Will Read.\n");
|
||||
err = ide_ata_access(ATA_READ, drive, lba, numsects, es, edi);
|
||||
|
||||
} else if (ide_devices[drive].Type == IDE_ATAPI)
|
||||
|
@ -119,18 +119,25 @@ static void default_handle(uint32_t key,int release,char c){
|
||||
|
||||
void init_keyboard(){
|
||||
key_status = (KEY_STATUS*) alloc(sizeof(KEY_STATUS));
|
||||
if(key_status == NULL) goto error;
|
||||
key_status->is_shift = 0;
|
||||
|
||||
key_char_queue = create_queue();
|
||||
head_listener = (struct key_listener*) kmalloc(sizeof(struct key_listener));
|
||||
if(head_listener == NULL) goto error;
|
||||
head_listener->func = default_handle;
|
||||
head_listener->lid = 0;
|
||||
head_listener->next = NULL;
|
||||
|
||||
register_interrupt_handler(0x21,handle_keyboard_input);
|
||||
|
||||
klogf(true,"Load PS/2 Keyboard device.\n");
|
||||
return;
|
||||
error:
|
||||
klogf(false,"Load PS/2 Keyboard device.\n");
|
||||
}
|
||||
|
||||
int handle_keyboard_input(){
|
||||
int handle_keyboard_input(registers_t *reg){
|
||||
unsigned char status = read_port(KEYBOARD_STATUS_PORT);
|
||||
uint32_t key = read_port(KEYBOARD_DATA_PORT);
|
||||
int release = key & 0xb10000000;
|
||||
|
91
src/driver/mouse.c
Normal file
91
src/driver/mouse.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include "../include/mouse.h"
|
||||
#include "../include/io.h"
|
||||
#include "../include/isr.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
uint8_t mouse_cycle = 0; //unsigned char
|
||||
int8_t mouse_byte[3]; //signed char
|
||||
int8_t mouse_x = 0; //signed char
|
||||
int8_t mouse_y = 0; //signed char
|
||||
|
||||
static void wait_KBC_sendready(void) {
|
||||
for (;;) {
|
||||
if ((io_in8(0x0064) & 0x02) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void mouse_handler(registers_t *a_r) {
|
||||
switch (mouse_cycle) {
|
||||
case 0:
|
||||
mouse_byte[0] = io_in8(0x60);
|
||||
mouse_cycle++;
|
||||
break;
|
||||
case 1:
|
||||
mouse_byte[1] = io_in8(0x60);
|
||||
mouse_cycle++;
|
||||
break;
|
||||
case 2:
|
||||
mouse_byte[2] = io_in8(0x60);
|
||||
mouse_x = mouse_byte[1];
|
||||
mouse_y = mouse_byte[2];
|
||||
mouse_cycle = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Mouse Mov: %d %d\n",mouse_x,mouse_y);
|
||||
}
|
||||
|
||||
void mouse_wait(uint8_t a_type) {
|
||||
unsigned int _time_out = 100000;
|
||||
if (a_type == 0) {
|
||||
while (_time_out--) {
|
||||
if ((io_in8(0x64) & 1) == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
while (_time_out--) {
|
||||
if ((io_in8(0x64) & 2) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void mouse_write(uint8_t a_write) {
|
||||
mouse_wait(1);
|
||||
io_out8(0x64, 0xD4);
|
||||
mouse_wait(1);
|
||||
io_out8(0x60, a_write);
|
||||
}
|
||||
|
||||
uint8_t mouse_read() {
|
||||
mouse_wait(0);
|
||||
return io_in8(0x60);
|
||||
}
|
||||
|
||||
void mouse_reset() {
|
||||
mouse_write(0xff);
|
||||
}
|
||||
|
||||
void mouse_install() {
|
||||
wait_KBC_sendready();
|
||||
io_out8(0x0064, 0xd4);
|
||||
wait_KBC_sendready();
|
||||
io_out8(0x0060, 0xf4);
|
||||
mouse_write(0xf3);
|
||||
mouse_write(200);
|
||||
mouse_write(0xf3);
|
||||
mouse_write(100);
|
||||
mouse_write(0xf3);
|
||||
mouse_write(80);
|
||||
mouse_write(0xf2);
|
||||
logkf("mouseId=%d\n", mouse_read());
|
||||
|
||||
register_interrupt_handler(12,mouse_handler);
|
||||
}
|
@ -104,7 +104,6 @@ void pci_config(unsigned int bus, unsigned int f, unsigned int equipment, unsign
|
||||
}
|
||||
|
||||
void init_pci(){
|
||||
printf("[\035kernel\036]: Loading pci device...\n");
|
||||
int PCI_NUM = 0;
|
||||
|
||||
PCI_ADDR_BASE = kmalloc(1 * 1024 * 1024);
|
||||
@ -155,6 +154,5 @@ void init_pci(){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[pci]: Device Loaded: %d\n",PCI_NUM);
|
||||
klogf(true,"PCI device loaded: %d\n",PCI_NUM);
|
||||
}
|
||||
|
@ -28,6 +28,16 @@ static void copy_char(uint32_t *vram, int off_x, int off_y, int x, int y, int x1
|
||||
}
|
||||
}
|
||||
|
||||
void drawPixel(uint32_t x, uint32_t y, uint32_t color) {
|
||||
if (x >= width
|
||||
|| y >= height) {
|
||||
return;
|
||||
}
|
||||
color = (color & 0xff) << 16 | (color & 0xff00) | (color & 0xff0000) >> 16;
|
||||
uint32_t *p = (uint32_t *)screen + y * width + x;
|
||||
*p = color;
|
||||
}
|
||||
|
||||
void vbe_scroll() {
|
||||
if (cx > c_width) {
|
||||
cx = 0;
|
||||
@ -198,7 +208,8 @@ void initVBE(multiboot_t *info) {
|
||||
width = info->framebuffer_width;
|
||||
height = info->framebuffer_height;
|
||||
color = 0xc6c6c6;
|
||||
back_color = 0x1c1c1c;
|
||||
//back_color = 0x1c1c1c;
|
||||
back_color = 0x000000;
|
||||
c_width = width / 9;
|
||||
c_height = height / 16;
|
||||
|
||||
|
@ -16,6 +16,7 @@ int init_vdisk() {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
vdisk_ctl[i].flag = 0; // 设置为未使用
|
||||
}
|
||||
klogf(true,"VDisk interface initialize.\n");
|
||||
}
|
||||
|
||||
int register_vdisk(vdisk vd) {
|
||||
|
11
src/fs/fat.c
11
src/fs/fat.c
@ -85,6 +85,7 @@ int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs) {
|
||||
if (!size) {
|
||||
return;
|
||||
@ -168,15 +169,7 @@ void file_savefile(int clustno, int size, char *buf, int *fat,
|
||||
}
|
||||
void *img = kmalloc(alloc_size);
|
||||
memclean((char *)img, alloc_size);
|
||||
memcpy(img, buf, size); // 把要写入的数据复制到新请求的内存地址
|
||||
// for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) {
|
||||
// uint32_t sec = (get_dm(vfs).FileDataAddress +
|
||||
// (clustno - 2) * get_dm(vfs).ClustnoBytes) /
|
||||
// get_dm(vfs).SectorBytes;
|
||||
// Disk_Write(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
|
||||
// img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
|
||||
// clustno = fat[clustno];
|
||||
// }
|
||||
memcpy(img, buf, size);
|
||||
int flag = 0, a, num = 0, sec_start = 0;
|
||||
for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) {
|
||||
uint32_t sec = (get_dm(vfs).FileDataAddress +
|
||||
|
@ -10,6 +10,7 @@
|
||||
vfs_t vfsstl[26];
|
||||
vfs_t vfsMount_Stl[26];
|
||||
vfs_t *vfs_now;
|
||||
bool hasFS;
|
||||
|
||||
static vfs_t *drive2fs(uint8_t drive) {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
@ -71,7 +72,6 @@ static void insert_str1(char *str, char *insert_str1, int pos) {
|
||||
}
|
||||
|
||||
bool vfs_mount_disk(uint8_t disk_number, uint8_t drive) {
|
||||
printf("Mount DISK ---- %02x\n", disk_number);
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (vfsMount_Stl[i].flag == 1 &&
|
||||
(vfsMount_Stl[i].drive == drive ||
|
||||
@ -95,6 +95,9 @@ bool vfs_mount_disk(uint8_t disk_number, uint8_t drive) {
|
||||
seat->drive = drive;
|
||||
seat->disk_number = disk_number;
|
||||
seat->flag = 1;
|
||||
|
||||
printf("Disk %c mount success!\n",disk_number);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -400,10 +403,10 @@ void init_vfs() {
|
||||
// PDEBUG("Set vfsstl[%d] & vfsMount_Stl[%d] OK.", i, i);
|
||||
}
|
||||
vfs_now = NULL;
|
||||
klogf(true,"Virtual File System initialize.\n");
|
||||
}
|
||||
|
||||
bool vfs_register_fs(vfs_t vfs) {
|
||||
printf("Register file system: %s\n", vfs.FSName);
|
||||
vfs_t *seat;
|
||||
seat = findSeat(vfsstl);
|
||||
if (!seat) {
|
||||
@ -411,5 +414,6 @@ bool vfs_register_fs(vfs_t vfs) {
|
||||
return false;
|
||||
}
|
||||
*seat = vfs;
|
||||
klogf(true,"Register file system: %s\n",vfs.FSName);
|
||||
return true;
|
||||
}
|
27
src/include/bmp.h
Normal file
27
src/include/bmp.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef CRASHPOWEROS_BMP_H
|
||||
#define CRASHPOWEROS_BMP_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t magic;
|
||||
uint32_t fileSize;
|
||||
uint32_t reserved;
|
||||
uint32_t bmpDataOffset;
|
||||
// bmp信息头开始
|
||||
uint32_t bmpInfoSize;
|
||||
uint32_t frameWidth;
|
||||
uint32_t frameHeight;
|
||||
uint16_t reservedValue; // 必须为0x0001
|
||||
uint16_t bitsPerPixel;
|
||||
uint32_t compressionMode;
|
||||
uint32_t frameSize;
|
||||
uint32_t horizontalResolution;
|
||||
uint32_t verticalResolution;
|
||||
uint32_t usedColorCount;
|
||||
uint32_t importantColorCount;
|
||||
} __attribute__((packed)) Bmp;
|
||||
|
||||
void display(Bmp *bmp,uint32_t x, uint32_t y, bool isTransparent);
|
||||
|
||||
#endif
|
@ -2,7 +2,11 @@
|
||||
#define CRASHPOWEROS_COMMON_H
|
||||
|
||||
#define OS_NAME "CoolPotOS"
|
||||
#define OS_VERSION "v0.2.5"
|
||||
#define OS_VERSION "v0.2.9"
|
||||
|
||||
// b 0x211972
|
||||
// b 0x20d0a6
|
||||
|
||||
|
||||
#define LONG_MAX 9223372036854775807L
|
||||
#define LONG_MIN -9223372036854775808L
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#define GDT_LENGTH 6
|
||||
|
||||
#define SA_RPL3 3
|
||||
|
||||
typedef struct gdt_entry_t {
|
||||
uint16_t limit_low; // 段基址 | 低16位置
|
||||
uint16_t base_low; // 段基址 | 高16位置
|
||||
@ -121,12 +123,38 @@ typedef struct tss_table {
|
||||
uint16_t iomap_base;
|
||||
} tss_entry;
|
||||
|
||||
typedef struct intr_frame_t {
|
||||
unsigned edi;
|
||||
unsigned esi;
|
||||
unsigned ebp;
|
||||
// 虽然 pushad 把 esp 也压入,但 esp 是不断变化的,所以会被 popad 忽略
|
||||
unsigned esp_dummy;
|
||||
|
||||
unsigned ebx;
|
||||
unsigned edx;
|
||||
unsigned ecx;
|
||||
unsigned eax;
|
||||
|
||||
unsigned gs;
|
||||
unsigned fs;
|
||||
unsigned es;
|
||||
unsigned ds;
|
||||
|
||||
unsigned eip;
|
||||
unsigned cs;
|
||||
unsigned eflags;
|
||||
unsigned esp;
|
||||
unsigned ss;
|
||||
} intr_frame_t;
|
||||
|
||||
void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
|
||||
void set_kernel_stack(uintptr_t stack);
|
||||
void set_tss_ss0(uintptr_t ss);
|
||||
|
||||
void gdt_install();
|
||||
void idt_install();
|
||||
|
||||
void idt_use_reg(uint8_t num,uint32_t base);
|
||||
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
|
||||
|
||||
#endif //CRASHPOWEROS_DESCRIPTION_TABLE_H
|
||||
|
6
src/include/desktop.h
Normal file
6
src/include/desktop.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef CRASHPOWEROS_DESKTOP_H
|
||||
#define CRASHPOWEROS_DESKTOP_H
|
||||
|
||||
void menu_sel();
|
||||
|
||||
#endif
|
3261
src/include/elf.h
3261
src/include/elf.h
File diff suppressed because it is too large
Load Diff
@ -105,6 +105,6 @@ int cur_task();
|
||||
void vbe_draw_char(char c,int32_t x,int32_t y);
|
||||
void draw_rect(int x0, int y0, int x1, int y1, int c);
|
||||
void initVBE(multiboot_t *multiboot);
|
||||
|
||||
void drawPixel(uint32_t x, uint32_t y, uint32_t color);
|
||||
|
||||
#endif
|
10
src/include/heap.h
Normal file
10
src/include/heap.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef CRASHPOWEROS_HEAP_H
|
||||
#define CRASHPOWEROS_HEAP_H
|
||||
|
||||
#include "task.h"
|
||||
|
||||
void *user_alloc(struct task_struct *user_t, size_t size);
|
||||
void use_free(struct task_struct *user_t,void *block);
|
||||
void *use_sbrk(struct task_struct *user_t,int incr);
|
||||
|
||||
#endif
|
@ -6,15 +6,23 @@
|
||||
#include "isr.h"
|
||||
|
||||
#define KHEAP_INITIAL_SIZE 0xf00000
|
||||
#define KHEAP_START 0xc0000000
|
||||
#define KHEAP_START 0xa0000000
|
||||
#define STACK_SIZE 32768
|
||||
|
||||
#define USER_START 0xb0000000
|
||||
#define USER_END (USER_START + 0xf00000)
|
||||
#define USER_HEAP_END (USER_END - STACK_SIZE)
|
||||
|
||||
#define US_B_START 0xe0000000
|
||||
#define US_B_END 0xe1000000
|
||||
|
||||
#define INDEX_FROM_BIT(a) (a / (8*4))
|
||||
#define OFFSET_FROM_BIT(a) (a % (8*4))
|
||||
|
||||
typedef char ALIGN[16];
|
||||
|
||||
#include "multiboot.h"
|
||||
#include "common.h"
|
||||
|
||||
typedef struct page {
|
||||
uint32_t present: 1;
|
||||
@ -24,17 +32,17 @@ typedef struct page {
|
||||
uint32_t dirty: 1;
|
||||
uint32_t unused: 7;
|
||||
uint32_t frame: 20;
|
||||
} page_t;
|
||||
}__attribute__((packaged)) page_t;
|
||||
|
||||
typedef struct page_table {
|
||||
page_t pages[1024];
|
||||
} page_table_t;
|
||||
}__attribute__((packaged)) page_table_t;
|
||||
|
||||
typedef struct page_directory {
|
||||
page_table_t *tables[1024];
|
||||
uint32_t tablesPhysical[1024];
|
||||
uint32_t physicalAddr;
|
||||
} page_directory_t;
|
||||
}__attribute__((packaged)) page_directory_t;
|
||||
|
||||
typedef union header {
|
||||
struct {
|
||||
@ -57,7 +65,7 @@ void *memmove(void *dest, const void *src, size_t num);
|
||||
|
||||
void switch_page_directory(page_directory_t *dir);
|
||||
|
||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir);
|
||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir,bool ist);
|
||||
|
||||
void alloc_frame(page_t *page, int is_kernel, int is_writable);
|
||||
|
||||
|
12
src/include/mouse.h
Normal file
12
src/include/mouse.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef CRASHPOWEROS_MOUSE_H
|
||||
#define CRASHPOWEROS_MOUSE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
uint8_t mouse_read();
|
||||
void mouse_reset();
|
||||
void mouse_wait(uint8_t a_type);
|
||||
void mouse_write(uint8_t a_write);
|
||||
void mouse_install();
|
||||
|
||||
#endif
|
@ -1,4 +1,13 @@
|
||||
#ifndef CRASHPOWEROS_PANIC_H
|
||||
#define CRASHPOWEROS_PANIC_H
|
||||
|
||||
enum PANIC_TYPE{
|
||||
ILLEGAL_KERNEL_STATUS,
|
||||
OUT_OF_MEMORY,
|
||||
KERNEL_PAGE_FAULT
|
||||
};
|
||||
|
||||
void panic_pane(char* msg,enum PANIC_TYPE type);
|
||||
void init_eh();
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
void printf(const char *formet, ...);
|
||||
@ -14,5 +16,6 @@ void putchar(char c);
|
||||
void logk(char *message);
|
||||
void logkf(char *formet,...);
|
||||
void screen_clear();
|
||||
void klogf(bool isok,char* fmt,...);
|
||||
|
||||
#endif //CRASHPOWEROS_PRINTF_H
|
||||
|
@ -2,6 +2,11 @@
|
||||
#define CRASHPOWEROS_TASK_H
|
||||
|
||||
#include "memory.h"
|
||||
#include "vfs.h"
|
||||
|
||||
typedef struct {
|
||||
int (*main)(int argc,char* * argv);
|
||||
}user_func_t;
|
||||
|
||||
typedef
|
||||
enum task_state {
|
||||
@ -25,8 +30,14 @@ struct context {
|
||||
struct task_struct {
|
||||
volatile task_state state; // 进程当前状态
|
||||
int pid; // 进程标识符
|
||||
int mem_size; //内存利用率
|
||||
char *name; // 进程名
|
||||
void *stack; // 进程的内核栈地址
|
||||
header_t *head;
|
||||
header_t *tail;
|
||||
bool isUser;
|
||||
uint32_t program_break;
|
||||
uint32_t program_break_end;
|
||||
page_directory_t *pgd_dir; // 进程页表
|
||||
struct context context; // 上下文信息
|
||||
struct task_struct *next; // 链表指针
|
||||
@ -60,4 +71,7 @@ void start_task(struct task_struct *task);
|
||||
|
||||
int get_procs();
|
||||
|
||||
void switch_to_user_mode(uint32_t func);
|
||||
|
||||
int32_t user_process(char* path, char *name);
|
||||
#endif //CRASHPOWEROS_TASK_H
|
||||
|
@ -45,6 +45,10 @@ void set_kernel_stack(uintptr_t stack) {
|
||||
tss.esp0 = stack;
|
||||
}
|
||||
|
||||
void set_tss_ss0(uintptr_t ss){
|
||||
tss.ss0 = ss;
|
||||
}
|
||||
|
||||
void gdt_install() {
|
||||
gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
|
||||
gdt_ptr.base = (uint32_t)&gdt_entries;
|
||||
|
66
src/kernel/heap.c
Normal file
66
src/kernel/heap.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "../include/heap.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
extern struct task_struct *current;
|
||||
|
||||
static header_t *use_get_free_block(struct task_struct *user_t, size_t size) {
|
||||
header_t *curr = user_t->head;
|
||||
while (curr) {
|
||||
if (curr->s.is_free && curr->s.size >= size) return curr;
|
||||
curr = curr->s.next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *use_sbrk(struct task_struct *user_t,int incr) {
|
||||
if (user_t->program_break + incr >= (user_t->program_break_end)) return (void *) -1;
|
||||
void *prev_break = user_t->program_break;
|
||||
user_t->program_break += incr;
|
||||
return prev_break;
|
||||
}
|
||||
|
||||
void *user_alloc(struct task_struct *user_t, size_t size) {
|
||||
uint32_t total_size;
|
||||
void *block;
|
||||
header_t *header;
|
||||
if (!size) return NULL;
|
||||
header = use_get_free_block(user_t,size);
|
||||
if (header) {
|
||||
header->s.is_free = 0;
|
||||
return (void *) (header + 1);
|
||||
}
|
||||
total_size = sizeof(header_t) + size;
|
||||
block = use_sbrk(user_t,total_size);
|
||||
if (block == (void *) -1) return NULL;
|
||||
header = block;
|
||||
header->s.size = size;
|
||||
header->s.is_free = 0;
|
||||
header->s.next = NULL;
|
||||
if (!user_t->head) user_t->head = header;
|
||||
if (user_t->tail) user_t->tail->s.next = header;
|
||||
user_t->tail = header;
|
||||
return (void *) (header + 1);
|
||||
}
|
||||
|
||||
void use_free(struct task_struct *user_t,void *block) {
|
||||
header_t *header, *tmp;
|
||||
if (!block) return;
|
||||
header = (header_t *) block - 1;
|
||||
if ((char *) block + header->s.size == user_t->program_break) {
|
||||
if (user_t->head == user_t->tail) user_t->head = user_t->tail = NULL;
|
||||
else {
|
||||
tmp = user_t->head;
|
||||
while (tmp) {
|
||||
if (tmp->s.next == user_t->tail) {
|
||||
tmp->s.next = NULL;
|
||||
user_t->tail = tmp;
|
||||
}
|
||||
tmp = tmp->s.next;
|
||||
}
|
||||
}
|
||||
use_sbrk(user_t,0 - sizeof(header_t) - header->s.size);
|
||||
return;
|
||||
}
|
||||
header->s.is_free = 1;
|
||||
}
|
||||
|
@ -9,6 +9,15 @@ idt_ptr_t idt_ptr;
|
||||
|
||||
extern void idt_flush(uint32_t);
|
||||
|
||||
void idt_use_reg(uint8_t num,uint32_t base){
|
||||
idt_entries[num].base_low = base & 0xFFFF;
|
||||
idt_entries[num].base_high = (base >> 16) & 0xFFFF; // 拆成低位和高位
|
||||
|
||||
idt_entries[num].sel = 0x08;
|
||||
idt_entries[num].always0 = 0;
|
||||
idt_entries[num].flags = 0x8E | 0x60;
|
||||
}
|
||||
|
||||
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||||
idt_entries[num].base_low = base & 0xFFFF;
|
||||
idt_entries[num].base_high = (base >> 16) & 0xFFFF; // 拆成低位和高位
|
||||
|
@ -18,12 +18,16 @@
|
||||
#include "../include/vfs.h"
|
||||
#include "../include/fat.h"
|
||||
#include "../include/iso9660.h"
|
||||
#include "../include/panic.h"
|
||||
#include "../include/mouse.h"
|
||||
#include "../include/desktop.h"
|
||||
|
||||
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
|
||||
|
||||
extern uint32_t end;
|
||||
extern int status;
|
||||
extern vdisk vdisk_ctl[10];
|
||||
extern bool hasFS;
|
||||
uint32_t placement_address = (uint32_t) & end;
|
||||
|
||||
void reset_kernel(){
|
||||
@ -38,6 +42,8 @@ void shutdown_kernel(){
|
||||
kill_all_task();
|
||||
clock_sleep(10);
|
||||
power_off();
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint32_t memory_all(){
|
||||
@ -70,59 +76,72 @@ void kernel_main(multiboot_t *multiboot) {
|
||||
}
|
||||
|
||||
initVBE(multiboot);
|
||||
|
||||
printf("[kernel]: VBE driver load success!\n");
|
||||
printf("CPOS_Kernel %s (GRUB Multiboot) on an i386.\n",OS_VERSION);
|
||||
printf("Memory Size: %dMB\n",(multiboot->mem_upper + multiboot->mem_lower) / 1024 + 1);
|
||||
printf("Graphics[ width: %d | height: %d | address: %08x ]\n",multiboot->framebuffer_width,multiboot->framebuffer_height,multiboot->framebuffer_addr);
|
||||
gdt_install();
|
||||
idt_install();
|
||||
printf("[kernel]: description table config success!\n");
|
||||
init_timer(1);
|
||||
acpi_install();
|
||||
printf("[kernel]: ACPI enable success!\n");
|
||||
init_page(multiboot);
|
||||
printf("[kernel]: page set success!\n");
|
||||
|
||||
init_sched();
|
||||
printf("[kernel]: task load success!\n");
|
||||
init_keyboard();
|
||||
printf("[kernel]: Keyboard driver load success!\n");
|
||||
|
||||
init_pit();
|
||||
io_sti();
|
||||
init_pci();
|
||||
printf("[kernel]: PCI driver load success!\n");
|
||||
init_vdisk();
|
||||
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
|
||||
printf("[kernel]: Disk driver load success!\n");
|
||||
init_vfs();
|
||||
Register_fat_fileSys();
|
||||
printf("iso\n");
|
||||
init_iso9660();
|
||||
printf("[kernel]: FileSystem load success!\n");
|
||||
syscall_install();
|
||||
|
||||
|
||||
char disk_id = '0';
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (vdisk_ctl[i].flag) {
|
||||
vdisk vd = vdisk_ctl[i];
|
||||
char id = i + ('A');
|
||||
vfs_mount_disk(id,id);
|
||||
if(vfs_mount_disk(id,id)){
|
||||
disk_id = id;
|
||||
klogf(true,"Mount disk: %c\n",disk_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
init_eh();
|
||||
hasFS = false;
|
||||
if(disk_id != '0'){
|
||||
if(vfs_change_disk(disk_id)){
|
||||
klogf(true,"Chang default mounted disk.\n");
|
||||
hasFS = true;
|
||||
}
|
||||
} else klogf(false,"Unable to find available IDE devices.\n");
|
||||
|
||||
|
||||
//vfs_mount_disk('A','A');
|
||||
if(vfs_change_disk('A'))
|
||||
printf("[FileSystem]: Change disk win!\n");
|
||||
|
||||
if(pcnet_find_card()){
|
||||
bool pcnet_init = pcnet_find_card();
|
||||
klogf(pcnet_init,"Enable network device pcnet.\n");
|
||||
if(pcnet_init){
|
||||
//init_pcnet_card();
|
||||
} else printf("[kernel]: Cannot found pcnet.\n");
|
||||
|
||||
print_cpu_id();
|
||||
|
||||
}
|
||||
klogf(true,"Kernel load done!\n");
|
||||
printf("\n\n");
|
||||
clock_sleep(25);
|
||||
|
||||
int pid = kernel_thread(setup_shell, NULL, "CPOS-Shell");
|
||||
kernel_thread(check_task,&pid,"CPOS-SHELL-CHECK");
|
||||
// vfs_change_disk('B');
|
||||
vfs_change_path("apps");
|
||||
|
||||
user_process("init.bin","User-Init");
|
||||
user_process("service.bin","Service");
|
||||
|
||||
print_proc();
|
||||
|
||||
//menu_sel();
|
||||
|
||||
//uint32_t pid = kernel_thread(setup_shell,NULL,"CPOS-Shell");
|
||||
//kernel_thread(check_task,&pid,"CPOS-SC");
|
||||
|
||||
//panic_pane("Proccess out of memory error!",OUT_OF_MEMORY);
|
||||
|
||||
for (;;) {
|
||||
io_hlt();
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "../include/memory.h"
|
||||
#include "../include/task.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
header_t *head = NULL, *tail = NULL; // 内存块链表
|
||||
extern page_directory_t *current_directory;
|
||||
extern uint32_t end; // declared in linker.ld
|
||||
static uint32_t placement_address = (uint32_t) &end;
|
||||
void *program_break, *program_break_end;
|
||||
extern struct task_struct *current;
|
||||
|
||||
uint32_t memory_usage(){
|
||||
header_t *curr = head;
|
||||
@ -36,7 +39,7 @@ static uint32_t kmalloc_int(size_t sz, uint32_t align, uint32_t *phys) {
|
||||
void *addr = alloc(sz); // 直接malloc,align丢掉了
|
||||
if (phys) {
|
||||
// 需要物理地址,先找到对应页
|
||||
page_t *page = get_page((uint32_t) addr, 0, current_directory);
|
||||
page_t *page = get_page((uint32_t) addr, 0, current_directory,false);
|
||||
*phys = page->frame * 0x1000 + ((uint32_t) addr & 0x00000FFF);
|
||||
}
|
||||
return (uint32_t) addr;
|
||||
@ -113,7 +116,6 @@ void kfree(void *block) {
|
||||
header_t *header, *tmp;
|
||||
if (!block) return;
|
||||
header = (header_t *) block - 1;
|
||||
|
||||
if ((char *) block + header->s.size == program_break) {
|
||||
if (head == tail) head = tail = NULL;
|
||||
else {
|
||||
|
@ -51,7 +51,9 @@ uint32_t first_frame() {
|
||||
}
|
||||
|
||||
void alloc_frame(page_t *page, int is_kernel, int is_writable) {
|
||||
if (page->frame) return;
|
||||
if (page->present) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
uint32_t idx = first_frame();
|
||||
if (idx == (uint32_t) - 1) {
|
||||
@ -61,6 +63,7 @@ void alloc_frame(page_t *page, int is_kernel, int is_writable) {
|
||||
}
|
||||
|
||||
set_frame(idx * 0x1000);
|
||||
memset(page,0,4);
|
||||
page->present = 1; // 现在这个页存在了
|
||||
page->rw = is_writable ? 1 : 0; // 是否可写由is_writable决定
|
||||
page->user = is_kernel ? 0 : 1; // 是否为用户态由is_kernel决定
|
||||
@ -93,12 +96,9 @@ void page_flush(page_directory_t *dir){
|
||||
}
|
||||
|
||||
void page_switch(page_directory_t *dir){
|
||||
io_cli();
|
||||
current_directory = dir;
|
||||
logkf("TablePhy: %08x | KERPhy: %08x\n",(&dir->tablesPhysical),kernel_directory->tablesPhysical);
|
||||
asm volatile("mov %0, %%cr3" : : "r"(&dir->tablesPhysical)); // 设置cr3寄存器切换页表
|
||||
logk("Switch directory win!\n");
|
||||
io_sti();
|
||||
asm volatile("mov %0, %%cr3" : : "r"(&dir->tablesPhysical));
|
||||
|
||||
}
|
||||
|
||||
void switch_page_directory(page_directory_t *dir) {
|
||||
@ -111,17 +111,23 @@ void switch_page_directory(page_directory_t *dir) {
|
||||
asm volatile("mov %0, %%cr0" : : "r"(cr0));
|
||||
}
|
||||
|
||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir) {
|
||||
page_t *get_page(uint32_t address, int make, page_directory_t *dir,bool ist) {
|
||||
|
||||
address /= 0x1000;
|
||||
|
||||
uint32_t table_idx = address / 1024;
|
||||
if (dir->tables[table_idx]) return &dir->tables[table_idx]->pages[address % 1024];
|
||||
|
||||
if (dir->tables[table_idx]){
|
||||
page_t *pgg = &dir->tables[table_idx]->pages[address % 1024];
|
||||
return pgg;
|
||||
}
|
||||
else if (make) {
|
||||
uint32_t tmp;
|
||||
dir->tables[table_idx] = (page_table_t *) kmalloc_ap(sizeof(page_table_t), &tmp);
|
||||
dir->tables[table_idx] = (page_table_t *) kmalloc_i_ap(sizeof(page_table_t), &tmp);
|
||||
memset(dir->tables[table_idx], 0, 0x1000);
|
||||
dir->tablesPhysical[table_idx] = tmp | 0x7;
|
||||
return &dir->tables[table_idx]->pages[address % 1024];
|
||||
page_t *pgg = &dir->tables[table_idx]->pages[address % 1024];
|
||||
return pgg;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
@ -141,11 +147,11 @@ void page_fault(registers_t *regs) {
|
||||
if (present) {
|
||||
printf("Type: present;\n\taddress: %x \n", faulting_address);
|
||||
} else if (rw) {
|
||||
printf("Type: read-only;\n\taddress: %x", faulting_address);
|
||||
printf("Type: read-only;\n\taddress: %x\n", faulting_address);
|
||||
} else if (us) {
|
||||
printf("Type: user-mode;\n\taddres: %x", faulting_address);
|
||||
printf("Type: user-mode;\n\taddres: %x\n", faulting_address);
|
||||
} else if (reserved) {
|
||||
printf("Type: reserved;\n\taddress: %x", faulting_address);
|
||||
printf("Type: reserved;\n\taddress: %x\n", faulting_address);
|
||||
} else if (id) {
|
||||
printf("Type: decode address;\n\taddress: %x\n", faulting_address);
|
||||
}
|
||||
@ -162,7 +168,7 @@ void page_fault(registers_t *regs) {
|
||||
}
|
||||
|
||||
static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr) {
|
||||
page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr);
|
||||
page_table_t *table = (page_table_t *) kmalloc_i_ap(sizeof(page_table_t), physAddr);
|
||||
memset(table, 0, sizeof(page_directory_t));
|
||||
|
||||
int i;
|
||||
@ -220,25 +226,35 @@ void init_page(multiboot_t *mboot) {
|
||||
|
||||
while (i < placement_address + 0x30000) {
|
||||
// 内核部分对ring3而言可读不可写 | 无偏移页表映射
|
||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||
alloc_frame(get_page(i, 1, kernel_directory,false), 1, 1);
|
||||
i += 0x1000;
|
||||
}
|
||||
|
||||
unsigned int j = mboot->framebuffer_addr,size = mboot->framebuffer_height * mboot->framebuffer_width*mboot->framebuffer_bpp;
|
||||
|
||||
while (j <= mboot->framebuffer_addr + size){
|
||||
alloc_frame_line(get_page(j,1,kernel_directory),j,0,0);
|
||||
alloc_frame_line(get_page(j,1,kernel_directory,false),j,1,1);
|
||||
j += 0x1000;
|
||||
}
|
||||
|
||||
|
||||
for (int i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i++) {
|
||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||
alloc_frame(get_page(i, 1, kernel_directory,false), 1, 1);
|
||||
}
|
||||
|
||||
|
||||
register_interrupt_handler(14, page_fault);
|
||||
switch_page_directory(clone_directory(kernel_directory));
|
||||
switch_page_directory(kernel_directory);
|
||||
|
||||
program_break = (void *) KHEAP_START;
|
||||
program_break_end = (void *) (KHEAP_START + KHEAP_INITIAL_SIZE);
|
||||
|
||||
klogf(true,"Memory manager is enable\n"
|
||||
"Kernel: 0x00 - 0x%08x "
|
||||
"Framebuffer: 0x%08x - 0x%08x "
|
||||
"KernelHeap: 0x%08x - 0x%08x "
|
||||
"BaseFrame: 0x%08x\n",
|
||||
placement_address + 0x30000,
|
||||
mboot->framebuffer_addr,mboot->framebuffer_addr + size,
|
||||
KHEAP_START,KHEAP_START + KHEAP_INITIAL_SIZE,
|
||||
frames);
|
||||
}
|
||||
|
89
src/kernel/panic.c
Normal file
89
src/kernel/panic.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "../include/panic.h"
|
||||
#include "../include/task.h"
|
||||
#include "../include/isr.h"
|
||||
#include "../include/io.h"
|
||||
#include "../include/printf.h"
|
||||
#include "../include/bmp.h"
|
||||
#include "../include/vfs.h"
|
||||
#include "../include/timer.h"
|
||||
#include "../include/graphics.h"
|
||||
#include "../include/acpi.h"
|
||||
|
||||
extern struct task_struct *current;
|
||||
extern uint32_t *screen;
|
||||
extern uint32_t back_color;
|
||||
extern uint32_t color;
|
||||
extern int32_t cx;
|
||||
extern int32_t cy;
|
||||
extern uint32_t c_width;
|
||||
extern uint32_t c_height;
|
||||
Bmp *panic_bmp;
|
||||
|
||||
static GP_13(registers_t *reg){
|
||||
if(current->pid == 0){
|
||||
printf("Kernel PANIC(#GP), Please restart your CPOS Kernel.\n");
|
||||
while(1) io_hlt();
|
||||
}else {
|
||||
task_kill(current->pid);
|
||||
}
|
||||
}
|
||||
|
||||
static UD_6(registers_t *reg){
|
||||
if(current->pid == 0){
|
||||
printf("Kernel PANIC(#GP), Please restart your CPOS Kernel.\n");
|
||||
while(1) io_hlt();
|
||||
}else {
|
||||
task_kill(current->pid);
|
||||
}
|
||||
}
|
||||
|
||||
void panic_pane(char* msg,enum PANIC_TYPE type){
|
||||
io_cli();
|
||||
kill_all_task();
|
||||
back_color = 0x1e90ff;
|
||||
color = 0xffffff;
|
||||
screen_clear();
|
||||
if(panic_bmp != NULL)
|
||||
display(panic_bmp,0,0,true);
|
||||
cx = 10;
|
||||
cy = c_height - 10;
|
||||
|
||||
register uint32_t ebx asm("ebx");
|
||||
register uint32_t ecx asm("ecx");
|
||||
|
||||
printf("%s: %s\n",type == ILLEGAL_KERNEL_STATUS ? "ILLEGAL_KERNEL_STATUS" : (type == OUT_OF_MEMORY ? "OUT_OF_MEMORY" :(type == KERNEL_PAGE_FAULT ? "KERNEL_PAGE_FAULT" : "UNKOWN_ERROR")),msg);
|
||||
cx = 10;
|
||||
printf("EAX: %08x | EBX: %08x | ECX: %08x | ESP: %08x | EBP: %08x | EDI: %08x | ESI: %08x\n",current,ebx,ecx,current->context.esp
|
||||
,current->context.ebp,current->context.edi,current->context.esi);
|
||||
printf("\n\n");
|
||||
cx = 10;
|
||||
printf("Restarting your system...\n");
|
||||
|
||||
for (int i = 90; i < 1200; i++) {
|
||||
for (int j = 650; j < 670; j++) {
|
||||
drawPixel(i,j,0xffffff);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
sleep(100);
|
||||
power_reset();
|
||||
while (1) io_hlt();
|
||||
}
|
||||
|
||||
void init_eh(){
|
||||
register_interrupt_handler(13,GP_13);
|
||||
register_interrupt_handler(6,UD_6);
|
||||
|
||||
if(vfs_change_disk('B')){
|
||||
uint32_t size = vfs_filesize("panic.bmp");
|
||||
panic_bmp = NULL;
|
||||
if(size == -1){
|
||||
klogf(false,"Enable graphics user interface panic.\n");
|
||||
} else{
|
||||
Bmp *bmp = kmalloc(size);
|
||||
vfs_readfile("panic.bmp",bmp);
|
||||
panic_bmp = bmp;
|
||||
klogf(true,"Enable graphics user interface panic.\n");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,16 @@
|
||||
#include "../include/syscall.h"
|
||||
#include "../include/printf.h"
|
||||
#include "../include/isr.h"
|
||||
#include "../include/description_table.h"
|
||||
#include "../include/graphics.h"
|
||||
|
||||
void syscall_handler(registers_t *regs){
|
||||
if (regs->eax >= SYSCALL_NUM)
|
||||
void syscall_handler(registers_t regs){
|
||||
if(regs.eax == 0x01){
|
||||
putchar((regs.edx));
|
||||
}
|
||||
return;
|
||||
|
||||
void *location = NULL;//syscalls[regs->eax];
|
||||
|
||||
printf("Syscall Win: %08x\n",regs->eax);
|
||||
|
||||
int ret;
|
||||
asm volatile (" \
|
||||
push %1; \
|
||||
push %2; \
|
||||
push %3; \
|
||||
push %4; \
|
||||
push %5; \
|
||||
call *%6; \
|
||||
pop %%ebx; \
|
||||
pop %%ebx; \
|
||||
pop %%ebx; \
|
||||
pop %%ebx; \
|
||||
pop %%ebx; \
|
||||
" : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location));
|
||||
regs->eax = ret;
|
||||
}
|
||||
|
||||
void syscall_install(){
|
||||
register_interrupt_handler(0x80,syscall_handler);
|
||||
idt_use_reg(80, syscall_handler);
|
||||
}
|
@ -3,6 +3,15 @@
|
||||
#include "../include/graphics.h"
|
||||
#include "../include/io.h"
|
||||
#include "../include/description_table.h"
|
||||
#include "../include/vfs.h"
|
||||
#include "../include/timer.h"
|
||||
#include "../include/shell.h"
|
||||
#include "../include/heap.h"
|
||||
#include "../include/elf.h"
|
||||
|
||||
#define SA_RPL_MASK 0xFFFC
|
||||
#define SA_TI_MASK 0xFFFB
|
||||
#define GET_SEL(cs, rpl) ((cs & SA_RPL_MASK & SA_TI_MASK) | (rpl))
|
||||
|
||||
struct task_struct *running_proc_head = NULL;
|
||||
struct task_struct *wait_proc_head = NULL;
|
||||
@ -13,139 +22,143 @@ extern page_directory_t *kernel_directory;
|
||||
extern void switch_to(struct context *prev, struct context *next);
|
||||
|
||||
int now_pid = 0;
|
||||
int can_sche = 1;
|
||||
|
||||
struct task_struct* get_current(){
|
||||
struct task_struct *get_current() {
|
||||
return current;
|
||||
}
|
||||
|
||||
void print_proc_t(int *i,struct task_struct *base,struct task_struct *cur,int is_print){
|
||||
if(cur->pid == base->pid){
|
||||
if(is_print){
|
||||
void print_proc_t(int *i, struct task_struct *base, struct task_struct *cur, int is_print) {
|
||||
if (cur->pid == base->pid) {
|
||||
if (is_print) {
|
||||
switch (cur->state) {
|
||||
case TASK_RUNNABLE:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Running");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Running");
|
||||
break;
|
||||
case TASK_SLEEPING:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Sleeping");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Sleeping");
|
||||
break;
|
||||
case TASK_UNINIT:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Init");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Init");
|
||||
break;
|
||||
case TASK_ZOMBIE:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Zombie");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Zombie");
|
||||
break;
|
||||
case TASK_DEATH:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Death");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Death");
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*i)++;
|
||||
} else{
|
||||
if(is_print){
|
||||
} else {
|
||||
if (is_print) {
|
||||
switch (cur->state) {
|
||||
case TASK_RUNNABLE:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Running");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Running");
|
||||
break;
|
||||
case TASK_SLEEPING:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Sleeping");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Sleeping");
|
||||
break;
|
||||
case TASK_UNINIT:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Init");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Init");
|
||||
break;
|
||||
case TASK_ZOMBIE:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Zombie");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Zombie");
|
||||
break;
|
||||
case TASK_DEATH:
|
||||
printf("%-17s %-2d %s\n",cur->name,cur->pid,"Death");
|
||||
printf("%-17s %-2d %s %d\n", cur->name, cur->pid, "Death");
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*i)++;
|
||||
print_proc_t(i,base,cur->next,is_print);
|
||||
print_proc_t(i, base, cur->next, is_print);
|
||||
}
|
||||
}
|
||||
|
||||
int get_procs(){
|
||||
int get_procs() {
|
||||
int index = 0;
|
||||
print_proc_t(&index,current,current->next,0);
|
||||
print_proc_t(&index, current, current->next, 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
void print_proc(){
|
||||
void print_proc() {
|
||||
int index = 0;
|
||||
print_proc_t(&index,current,current->next,1);
|
||||
print_proc_t(&index, current, current->next, 1);
|
||||
printf("====---------------[Processes]----------------====\n");
|
||||
printf("Name Pid Status [All Proc: %d]\n\n",index);
|
||||
printf("Name Pid Status MemUsage [All Proc: %d]\n\n", index);
|
||||
}
|
||||
|
||||
static void found_task(int pid,struct task_struct *head,struct task_struct *base,struct task_struct **argv,int first){
|
||||
static void
|
||||
found_task(int pid, struct task_struct *head, struct task_struct *base, struct task_struct **argv, int first) {
|
||||
struct task_struct *t = base;
|
||||
if(t == NULL){
|
||||
if (t == NULL) {
|
||||
argv = NULL;
|
||||
return;
|
||||
}
|
||||
if(t->pid == pid){
|
||||
if (t->pid == pid) {
|
||||
*argv = t;
|
||||
return;
|
||||
} else{
|
||||
if(!first)
|
||||
if(head->pid == t->pid){
|
||||
} else {
|
||||
if (!first)
|
||||
if (head->pid == t->pid) {
|
||||
argv = NULL;
|
||||
return;
|
||||
}
|
||||
found_task(pid,head,t->next,argv,0);
|
||||
found_task(pid, head, t->next, argv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct task_struct* found_task_pid(int pid){
|
||||
struct task_struct *found_task_pid(int pid) {
|
||||
struct task_struct *argv = NULL;
|
||||
found_task(pid,running_proc_head,running_proc_head,&argv,1);
|
||||
if(argv == NULL){
|
||||
printf("Cannot found task Pid:[%d].\n",pid);
|
||||
found_task(pid, running_proc_head, running_proc_head, &argv, 1);
|
||||
if (argv == NULL) {
|
||||
printf("Cannot found task Pid:[%d].\n", pid);
|
||||
return NULL;
|
||||
}
|
||||
return argv;
|
||||
}
|
||||
|
||||
void wait_task(struct task_struct *task){
|
||||
void wait_task(struct task_struct *task) {
|
||||
task->state = TASK_SLEEPING;
|
||||
}
|
||||
|
||||
void start_task(struct task_struct *task){
|
||||
void start_task(struct task_struct *task) {
|
||||
task->state = TASK_RUNNABLE;
|
||||
}
|
||||
|
||||
void task_kill(int pid){
|
||||
void task_kill(int pid) {
|
||||
io_cli();
|
||||
struct task_struct *argv = found_task_pid(pid);
|
||||
if(argv == NULL){
|
||||
printf("Cannot found task Pid:[%d].\n",pid);
|
||||
if (argv == NULL) {
|
||||
printf("Cannot found task Pid:[%d].\n", pid);
|
||||
return;
|
||||
}
|
||||
if(argv->pid == 0){
|
||||
printf("[\033kernel\036]: Taskkill cannot terminate kernel processes.\n");
|
||||
if (argv->pid == 0) {
|
||||
printf("\033ff3030;[kernel]: Taskkill cannot terminate kernel processes.\033c6c6c6;\n");
|
||||
return;
|
||||
}
|
||||
argv->state = TASK_DEATH;
|
||||
printf("Taskkill process PID:%d Name:%s\n", current->pid, current->name);
|
||||
printf("Task [%s] exit code: -130.\n",argv->name);
|
||||
printf("Task [%s] exit code: -130.\n", argv->name);
|
||||
io_sti();
|
||||
|
||||
kfree(argv);
|
||||
struct task_struct *head = running_proc_head;
|
||||
struct task_struct *last = NULL;
|
||||
while (1){
|
||||
if(head->pid == argv->pid){
|
||||
while (1) {
|
||||
if (head->pid == argv->pid) {
|
||||
last->next = argv->next;
|
||||
io_sti();
|
||||
return;
|
||||
}
|
||||
last = head;
|
||||
head = head->next;
|
||||
}
|
||||
io_cli();
|
||||
}
|
||||
|
||||
void schedule() {
|
||||
if (current) {
|
||||
if(current->next->state == TASK_SLEEPING){
|
||||
if (current && can_sche) {
|
||||
if (current->next->state == TASK_SLEEPING) {
|
||||
change_task_to(current->next->next);
|
||||
return;
|
||||
}
|
||||
@ -159,22 +172,122 @@ void change_task_to(struct task_struct *next) {
|
||||
current = next;
|
||||
|
||||
page_switch(current->pgd_dir);
|
||||
set_kernel_stack(current->stack);
|
||||
set_kernel_stack(current->stack + STACK_SIZE); // 没有 TSACK_SIZE
|
||||
switch_to(&(prev->context), &(current->context));
|
||||
}
|
||||
}
|
||||
void n() {
|
||||
printf("Hello! User!\n");
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
||||
int32_t user_process(char *path, char *name){
|
||||
can_sche = 0;
|
||||
if(path == NULL){
|
||||
printf("Cannot create process! exec path is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
uint32_t size = vfs_filesize(path);
|
||||
if(size == -1){
|
||||
printf("Cannot font exec file\n");
|
||||
return -1;
|
||||
}
|
||||
io_cli();
|
||||
|
||||
int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) {
|
||||
struct task_struct *new_task = (struct task_struct *) kmalloc(STACK_SIZE);
|
||||
assert(new_task != NULL, "kern_thread: kmalloc error");
|
||||
assert(new_task != NULL, "user_pcb: kmalloc error");
|
||||
|
||||
// 将栈低端结构信息初始化为 0
|
||||
memset(new_task,0, sizeof(struct task_struct));
|
||||
memset(new_task, 0, sizeof(struct task_struct));
|
||||
|
||||
new_task->state = TASK_RUNNABLE;
|
||||
new_task->stack = current;
|
||||
new_task->pid = now_pid++;
|
||||
new_task->pgd_dir = clone_directory(current->pgd_dir) ;
|
||||
|
||||
page_directory_t *page = clone_directory(kernel_directory);
|
||||
new_task->pgd_dir = page;
|
||||
new_task->mem_size = 0;
|
||||
new_task->program_break = USER_START;
|
||||
new_task->program_break_end = USER_HEAP_END;
|
||||
new_task->name = name;
|
||||
new_task->isUser = 1;
|
||||
|
||||
io_sti();
|
||||
|
||||
page_switch(page);
|
||||
|
||||
for (int i = USER_START; i < USER_END;i++) {
|
||||
page_t *pg = get_page(i,1,page, false);
|
||||
alloc_frame(pg,0,1);
|
||||
}
|
||||
|
||||
char* buffer = user_alloc(new_task,size);
|
||||
|
||||
memset(buffer,0,size);
|
||||
vfs_readfile(path,buffer);
|
||||
|
||||
Elf32_Ehdr *ehdr = buffer;
|
||||
if(!elf32Validate(ehdr)){
|
||||
printf("Unknown exec file format.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t main = load_elf(ehdr,page);
|
||||
|
||||
printf("Main ADDRESS: %08x\n",main);
|
||||
|
||||
uint32_t *stack_top = (uint32_t * )((uint32_t) new_task + STACK_SIZE);
|
||||
|
||||
*(--stack_top) = (uint32_t) main;
|
||||
*(--stack_top) = (uint32_t) kthread_exit;
|
||||
*(--stack_top) = (uint32_t) switch_to_user_mode;
|
||||
|
||||
new_task->context.esp = (uint32_t) new_task + STACK_SIZE - sizeof(uint32_t) * 3;
|
||||
|
||||
// 设置新任务的标志寄存器未屏蔽中断,很重要
|
||||
new_task->context.eflags = 0x200;
|
||||
new_task->next = running_proc_head;
|
||||
|
||||
page_switch(kernel_directory);
|
||||
|
||||
// 找到当前进任务队列,插入到末尾
|
||||
struct task_struct *tailt = running_proc_head;
|
||||
assert(tailt != NULL, "Must init sched!");
|
||||
|
||||
while (tailt->next != running_proc_head) {
|
||||
tailt = tailt->next;
|
||||
}
|
||||
tailt->next = new_task;
|
||||
can_sche = 1;
|
||||
io_sti();
|
||||
return new_task->pid;
|
||||
}
|
||||
|
||||
|
||||
int32_t kernel_thread(int (*fn)(void *), void *arg, char *name) {
|
||||
io_cli();
|
||||
struct task_struct *new_task = (struct task_struct *) kmalloc(STACK_SIZE);
|
||||
assert(new_task != NULL, "kern_thread: kmalloc error");
|
||||
|
||||
// 将栈低端结构信息初始化为 0
|
||||
memset(new_task, 0, sizeof(struct task_struct));
|
||||
|
||||
new_task->state = TASK_RUNNABLE;
|
||||
new_task->stack = current;
|
||||
new_task->pid = now_pid++;
|
||||
new_task->pgd_dir = kernel_directory;
|
||||
new_task->mem_size = 0;
|
||||
new_task->isUser = 0;
|
||||
|
||||
extern header_t *head;
|
||||
extern header_t *tail;
|
||||
extern void *program_break;
|
||||
extern void *program_break_end;
|
||||
current->head = head;
|
||||
current->tail = tail;
|
||||
current->program_break = program_break;
|
||||
current->program_break_end = program_break_end;
|
||||
|
||||
new_task->name = name;
|
||||
|
||||
@ -191,14 +304,14 @@ int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) {
|
||||
new_task->next = running_proc_head;
|
||||
|
||||
// 找到当前进任务队列,插入到末尾
|
||||
struct task_struct *tail = running_proc_head;
|
||||
assert(tail != NULL, "Must init sched!");
|
||||
struct task_struct *tailt = running_proc_head;
|
||||
assert(tailt != NULL, "Must init sched!");
|
||||
|
||||
while (tail->next != running_proc_head) {
|
||||
tail = tail->next;
|
||||
while (tailt->next != running_proc_head) {
|
||||
tailt = tailt->next;
|
||||
}
|
||||
tail->next = new_task;
|
||||
|
||||
tailt->next = new_task;
|
||||
io_sti();
|
||||
return new_task->pid;
|
||||
}
|
||||
|
||||
@ -209,18 +322,64 @@ void kthread_exit() {
|
||||
while (1);
|
||||
}
|
||||
|
||||
void kill_all_task(){
|
||||
void kill_all_task() {
|
||||
struct task_struct *head = running_proc_head;
|
||||
while (1){
|
||||
while (1) {
|
||||
head = head->next;
|
||||
if(head == NULL || head->pid == running_proc_head->pid){
|
||||
if (head == NULL || head->pid == running_proc_head->pid) {
|
||||
return;
|
||||
}
|
||||
if(head->pid == current->pid) continue;
|
||||
if (head->pid == current->pid) continue;
|
||||
task_kill(head->pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define SA_RPL3 3
|
||||
void A() {
|
||||
printf("USE3 HELLO!\n");
|
||||
asm("hlt");
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
||||
void switch_to_user_mode(uint32_t func) {
|
||||
io_cli();
|
||||
set_kernel_stack(current->stack + STACK_SIZE);
|
||||
unsigned esp = USER_END;
|
||||
current->context.eflags = (0 << 12 | 0b10 | 1 << 9);
|
||||
intr_frame_t iframe;
|
||||
iframe.edi = 1;
|
||||
iframe.esi = 2;
|
||||
iframe.ebp = 3;
|
||||
iframe.esp_dummy = 4;
|
||||
iframe.ebx = 5;
|
||||
iframe.edx = 6;
|
||||
iframe.ecx = 7;
|
||||
iframe.eax = 8;
|
||||
|
||||
iframe.gs = GET_SEL(4 * 8, SA_RPL3);
|
||||
iframe.ds = GET_SEL(4 * 8, SA_RPL3);
|
||||
iframe.es = GET_SEL(4 * 8, SA_RPL3);
|
||||
iframe.fs = GET_SEL(4 * 8, SA_RPL3);
|
||||
|
||||
iframe.ss = GET_SEL(4 * 8, SA_RPL3);
|
||||
iframe.cs = GET_SEL(3 * 8, SA_RPL3);
|
||||
|
||||
iframe.eip = func; //用户可执行程序入口
|
||||
iframe.eflags = (0 << 12 | 0b10 | 1 << 9);
|
||||
iframe.esp = esp; // 设置用户态堆栈
|
||||
|
||||
intr_frame_t *a = &iframe;
|
||||
asm volatile("movl %0, %%esp\n"
|
||||
"popa\n"
|
||||
"pop %%gs\n"
|
||||
"pop %%fs\n"
|
||||
"pop %%es\n"
|
||||
"pop %%ds\n"
|
||||
"iret" ::"m"(a));
|
||||
}
|
||||
|
||||
void init_sched() {
|
||||
// 为当前执行流创建信息结构体 该结构位于当前执行流的栈最低端
|
||||
current = (struct task_struct *) kmalloc(sizeof(struct task_struct));
|
||||
@ -230,8 +389,19 @@ void init_sched() {
|
||||
current->stack = current; // 该成员指向栈低地址
|
||||
current->pgd_dir = kernel_directory;
|
||||
current->name = "CPOS-System";
|
||||
|
||||
current->mem_size = 0;
|
||||
current->next = current;
|
||||
current->isUser = 0;
|
||||
|
||||
extern header_t *head;
|
||||
extern header_t *tail;
|
||||
extern void *program_break;
|
||||
extern void *program_break_end;
|
||||
current->head = head;
|
||||
current->tail = tail;
|
||||
current->program_break = program_break;
|
||||
current->program_break_end = program_break_end;
|
||||
|
||||
running_proc_head = current;
|
||||
klogf(true,"Load task schedule. | KernelTaskName: %s PID: %d\n",current->name,current->pid);
|
||||
}
|
@ -58,7 +58,6 @@ void init_pit(void) {
|
||||
}
|
||||
|
||||
void init_timer(uint32_t timer) {
|
||||
printf("REG TIMER INT: %d, function address: %08x.\n",IRQ0, &timer_handle);
|
||||
register_interrupt_handler(IRQ0, &timer_handle);
|
||||
uint32_t divisor = 1193180 / timer;
|
||||
|
||||
|
5
src/sysapp/desktop.c
Normal file
5
src/sysapp/desktop.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "../include/desktop.h"
|
||||
|
||||
void menu_sel(){
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
#include "../include/panic.h"
|
@ -12,6 +12,7 @@
|
||||
|
||||
extern Queue *key_char_queue;
|
||||
extern vdisk vdisk_ctl[10];
|
||||
extern bool hasFS;
|
||||
|
||||
char getc() {
|
||||
while (key_char_queue->size == 0x00) {
|
||||
@ -134,6 +135,11 @@ void cmd_mkdir(int argc, char **argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!hasFS){
|
||||
printf("Cannot find fs in this disk.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vfs_file *file = get_cur_file(argv[1]);
|
||||
|
||||
if(file != NULL){
|
||||
@ -152,6 +158,11 @@ void cmd_del(int argc, char **argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!hasFS){
|
||||
printf("Cannot find fs in this disk.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vfs_file *file = get_cur_file(argv[1]);
|
||||
|
||||
if(file == NULL){
|
||||
@ -213,6 +224,10 @@ void cmd_cd(int argc, char **argv) {
|
||||
print("[Shell-CD]: If there are too few parameters, please specify the path.\n");
|
||||
return;
|
||||
}
|
||||
if(!hasFS){
|
||||
printf("Cannot find fs in this disk.\n");
|
||||
return;
|
||||
}
|
||||
if (vfs_change_path(argv[1]) == 0) printf("Invalid path.\n");
|
||||
}
|
||||
|
||||
@ -229,6 +244,11 @@ void cmd_type(int argc,char ** argv){
|
||||
print("[Shell-TYPE]: If there are too few parameters, please specify the path.\n");
|
||||
return;
|
||||
}
|
||||
if(!hasFS){
|
||||
printf("Cannot find fs in this disk.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char *buffer;
|
||||
buffer = (char*) kmalloc(vfs_filesize(argv[1]));
|
||||
|
||||
@ -335,7 +355,7 @@ void setup_shell() {
|
||||
|
||||
screen_clear();
|
||||
|
||||
printf("Welcome to %s %s (CPOS Kernel x86_64)\n"
|
||||
printf("Welcome to %s %s (CPOS Kernel i386)\n"
|
||||
"\n"
|
||||
" * SourceCode: https://github.com/xiaoyi1212/CoolPotOS\n"
|
||||
" * Website: https://github.com/plos-clan\n"
|
||||
@ -360,7 +380,15 @@ void setup_shell() {
|
||||
char *buffer[255];
|
||||
|
||||
while (1) {
|
||||
vfs_getPath(buffer);
|
||||
if(hasFS) vfs_getPath(buffer);
|
||||
else{
|
||||
buffer[0] = 'n';
|
||||
buffer[1] = 'o';
|
||||
buffer[2] = '_';
|
||||
buffer[3] = 'f';
|
||||
buffer[4] = 's';
|
||||
buffer[5] = '\0';
|
||||
}
|
||||
printf("\03343cd80;%s@localhost: \0334169E1;%s\\\033c6c6c6;$ ", user1, buffer);
|
||||
if (gets(com, MAX_COMMAND_LEN) <= 0) continue;
|
||||
argc = cmd_parse(com, argv, ' ');
|
||||
@ -414,6 +442,6 @@ void setup_shell() {
|
||||
print("disk[list|<ID>|cg<ID>]List or view disks.\n");
|
||||
print("cd <path> Change shell top directory.\n");
|
||||
print("sb3 <name> Player a wav sound file.\n");
|
||||
} else printf("\033[Shell]: Unknown command '%s'.\n", argv[0]);
|
||||
} else printf("\033ff3030;[Shell]: Unknown command '%s'.\033c6c6c6;\n", argv[0]);
|
||||
}
|
||||
}
|
||||
|
23
src/util/bmp.c
Normal file
23
src/util/bmp.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "../include/bmp.h"
|
||||
#include "../include/graphics.h"
|
||||
|
||||
void display(Bmp *bmp,uint32_t x, uint32_t y, bool isTransparent) {
|
||||
if (bmp->magic != 0x4d42 || bmp->bitsPerPixel != 24)
|
||||
return;
|
||||
uint8_t *data = (uint8_t *)bmp + bmp->bmpDataOffset;
|
||||
for (uint32_t yOffset = 0; yOffset < bmp->frameHeight; ++yOffset) {
|
||||
for (uint32_t xOffset = 0; xOffset < bmp->frameWidth; ++xOffset) {
|
||||
uint32_t offset = (yOffset * bmp->frameWidth + xOffset) * 3;
|
||||
uint8_t b = data[offset + 0];
|
||||
uint8_t g = data[offset + 1];
|
||||
uint8_t r = data[offset + 2];
|
||||
uint32_t color = (r << 16) | (g << 8) | b;
|
||||
if (isTransparent && color == 0)
|
||||
continue;
|
||||
drawPixel(x + xOffset, y + bmp->frameHeight - 1 - yOffset, color);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
56
src/util/elf.c
Normal file
56
src/util/elf.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "../include/elf.h"
|
||||
#include "../include/common.h"
|
||||
|
||||
#define MAX(a, b) a > b ? a : b
|
||||
|
||||
static uint32_t div_round_up(uint32_t num, uint32_t size) {
|
||||
return (num + size - 1) / size;
|
||||
}
|
||||
|
||||
bool elf32Validate(Elf32_Ehdr *hdr) {
|
||||
return hdr->e_ident[EI_MAG0] == ELFMAG0 && hdr->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
hdr->e_ident[EI_MAG2] == ELFMAG2 && hdr->e_ident[EI_MAG3] == ELFMAG3;
|
||||
}
|
||||
|
||||
void load_segment(Elf32_Phdr *phdr,page_directory_t *pdt, void *elf) {
|
||||
unsigned int p = div_round_up(phdr->p_memsz, 0x1000);
|
||||
int d = phdr->p_paddr;
|
||||
if (d & 0x00000fff) {
|
||||
unsigned e = d + phdr->p_memsz;
|
||||
d = d & 0xfffff000;
|
||||
e &= 0xfffff000;
|
||||
p = (e - d) / 0x1000 + 1;
|
||||
}
|
||||
for (unsigned i = 0; i < p; i++) {
|
||||
alloc_frame(get_page(d + i * 0x1000,1,pdt,false),0,1);
|
||||
}
|
||||
memcpy(phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz);
|
||||
if (phdr->p_memsz > phdr->p_filesz) { // 这个是bss段
|
||||
memset(phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t load_elf(Elf32_Ehdr *hdr,page_directory_t *pdt) {
|
||||
Elf32_Phdr *phdr = (Elf32_Phdr *)((uint32_t)hdr + hdr->e_phoff);
|
||||
for (int i = 0; i < hdr->e_phnum; i++) {
|
||||
load_segment(phdr,pdt, (void *)hdr);
|
||||
phdr++;
|
||||
}
|
||||
return hdr->e_entry;
|
||||
}
|
||||
|
||||
void elf32LoadData(Elf32_Ehdr *elfhdr, uint8_t *ptr) {
|
||||
uint8_t *p = (uint8_t *)elfhdr;
|
||||
for (int i = 0; i < elfhdr->e_shnum; i++) {
|
||||
Elf32_Shdr *shdr =
|
||||
(Elf32_Shdr *)(p + elfhdr->e_shoff + sizeof(Elf32_Shdr) * i);
|
||||
|
||||
if (shdr->sh_type != SHT_PROGBITS || !(shdr->sh_flags & SHF_ALLOC)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < shdr->sh_size; i++) {
|
||||
ptr[shdr->sh_addr + i] = p[shdr->sh_offset + i];
|
||||
}
|
||||
}
|
||||
}
|
@ -304,6 +304,20 @@ void printf(const char *formet, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void klogf(bool isok,char* fmt,...){
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
char *buf[1024] = {0};
|
||||
len = vsprintf(buf, fmt, ap);
|
||||
if(isok){
|
||||
printf("[ \03300ee76;OK\033c6c6c6; ]: %s",buf);
|
||||
} else{
|
||||
printf("[\033ee6363;FAILED\033c6c6c6;]: %s",buf);
|
||||
}
|
||||
}
|
||||
|
||||
void screen_clear(){
|
||||
if(vbe_status){
|
||||
vbe_clear();
|
||||
@ -333,6 +347,6 @@ void logkf(char *formet,...){
|
||||
}
|
||||
|
||||
void logk(char *message){
|
||||
for (size_t i = 0; i < strlen(message); i++)
|
||||
write_serial(message[i]);
|
||||
for (size_t i = 0; i < strlen(message); i++);
|
||||
//write_serial(message[i]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user