Lots of little things, Changed test output, Usermode test build
This commit is contained in:
parent
36e66600f5
commit
e9c4e993f4
15
Makefile
15
Makefile
@ -1,5 +1,5 @@
|
|||||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o\
|
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o\
|
||||||
usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o disk.o hexedit.o
|
paging.o fault.o tests.o kbd.o helper.o progs.o disk.o hexedit.o textedit.o
|
||||||
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding\
|
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding\
|
||||||
-march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
|
-march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
|
||||||
LFLAGS = -Wl,--gc-sections -Wl,--print-gc-sections -m32 -nostartfiles -nostdlib
|
LFLAGS = -Wl,--gc-sections -Wl,--print-gc-sections -m32 -nostartfiles -nostdlib
|
||||||
@ -18,11 +18,14 @@ $(OUTFILE): boot.bin kernel.bin
|
|||||||
# Write kernel beyond boot sector, maximum 128K (256 sectors)
|
# Write kernel beyond boot sector, maximum 128K (256 sectors)
|
||||||
dd bs=512 count=256 seek=1 conv=notrunc if=kernel.bin of=$@
|
dd bs=512 count=256 seek=1 conv=notrunc if=kernel.bin of=$@
|
||||||
|
|
||||||
boot.bin: boot.nasm
|
kernel.bin: out.o link.ld usermode.o
|
||||||
nasm -o $@ $<
|
clang $(LFLAGS) -Wl,-M -Tlink.ld -ffreestanding -o $@ out.o usermode.o
|
||||||
|
|
||||||
kernel.bin: out.o link.ld
|
usermode.o: usermode.bin
|
||||||
clang $(LFLAGS) -Wl,-M -Tlink.ld -ffreestanding -o $@ $<
|
objcopy -I binary -O elf32-i386 -B i386 $< $@
|
||||||
|
|
||||||
|
%.bin: %.nasm
|
||||||
|
nasm -o $@ $<
|
||||||
|
|
||||||
out.o: $(objects)
|
out.o: $(objects)
|
||||||
clang $(LFLAGS) -e entry -r -o $@ $^
|
clang $(LFLAGS) -e entry -r -o $@ $^
|
||||||
@ -38,4 +41,4 @@ virtdisk:
|
|||||||
echo -n -e '\x55\xaa' | dd bs=1 seek=510 conv=notrunc of=virtdisk.bin
|
echo -n -e '\x55\xaa' | dd bs=1 seek=510 conv=notrunc of=virtdisk.bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(objects) out.o kernel.bin boot.bin
|
rm -f $(objects) out.o kernel.bin boot.bin usermode.bin
|
||||||
|
43
disk.c
43
disk.c
@ -1,3 +1,4 @@
|
|||||||
|
#include "disk.h"
|
||||||
#include "v86defs.h"
|
#include "v86defs.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "dosfs/dosfs.h"
|
#include "dosfs/dosfs.h"
|
||||||
@ -9,14 +10,15 @@ extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
|
|||||||
#define DISKCACHESECTORMASK 7
|
#define DISKCACHESECTORMASK 7
|
||||||
#define DISKCACHESECTORSIZE 8
|
#define DISKCACHESECTORSIZE 8
|
||||||
#define DISKCACHEBLOCKCOUNT 128
|
#define DISKCACHEBLOCKCOUNT 128
|
||||||
uint8_t (*DiskCache)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE] = (uint8_t (*)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE])0x280000;
|
uint8_t (*const DiskCache)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE] = (uint8_t (* const)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE])0x280000;
|
||||||
uint32_t DiskCacheLastRead[DISKCACHEBLOCKCOUNT];
|
uint32_t DiskCacheLastRead[DISKCACHEBLOCKCOUNT];
|
||||||
uint32_t DiskCacheSector[DISKCACHEBLOCKCOUNT];
|
uint32_t DiskCacheSector[DISKCACHEBLOCKCOUNT];
|
||||||
|
|
||||||
extern uint32_t _gpf_eax_save;
|
extern uint32_t _gpf_eax_save;
|
||||||
extern uint32_t _gpf_eflags_save;
|
extern uint32_t _gpf_eflags_save;
|
||||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
|
extern uint16_t error_screen[80*50]; // defined in kernel.c
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute__((__no_caller_saved_registers__))
|
||||||
|
__attribute__((__noreturn__))
|
||||||
extern void error_environment(); // defined in kernel.c
|
extern void error_environment(); // defined in kernel.c
|
||||||
uint32_t numHead;
|
uint32_t numHead;
|
||||||
uint32_t secPerTrack;
|
uint32_t secPerTrack;
|
||||||
@ -48,12 +50,6 @@ void Disk_SetupCHS() {
|
|||||||
maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
|
||||||
useCHS = 1;
|
useCHS = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init Cache
|
|
||||||
for (int i = 0; i < DISKCACHEBLOCKCOUNT; i++) {
|
|
||||||
DiskCacheLastRead[i] = 0;
|
|
||||||
DiskCacheSector[i] = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint32_t TIMERVAL;
|
extern uint32_t TIMERVAL;
|
||||||
@ -95,26 +91,33 @@ void UpdateCache(uint32_t sector, uint8_t *buffer) {
|
|||||||
((uint32_t*)cache)[i] = ((uint32_t*)buffer)[i];
|
((uint32_t*)cache)[i] = ((uint32_t*)buffer)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
void InitCache() {
|
||||||
// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
|
for (int i = 0; i < DISKCACHEBLOCKCOUNT; i++) {
|
||||||
// the function will use that buffer for the Virtual 8086 process
|
DiskCacheLastRead[i] = 0;
|
||||||
// and copy to the other buffer after
|
DiskCacheSector[i] = -1;
|
||||||
uint8_t *v86buf = buffer;
|
|
||||||
if ((uintptr_t)v86buf >= 0x20000 && (uintptr_t)v86buf < 0x28000)
|
|
||||||
v86buf = (uint8_t *)0x28000;
|
|
||||||
else v86buf = (uint8_t *)0x20000;
|
|
||||||
|
|
||||||
// TODO This check should probably happen at the kernel level
|
|
||||||
if (useCHS == -1) {
|
|
||||||
Disk_SetupCHS();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE Must be run before reading from disk
|
||||||
|
void InitDisk() {
|
||||||
|
InitCache();
|
||||||
|
Disk_SetupCHS();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
|
||||||
uint8_t *cache = FindInCache(sector);
|
uint8_t *cache = FindInCache(sector);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
memcpy(buffer, cache, count * SECTOR_SIZE);
|
memcpy(buffer, cache, count * SECTOR_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE If the buffer provided is outside the 0x20000-0x2F000 range,
|
||||||
|
// the function will use 0x20000 for the Virtual 8086 process
|
||||||
|
// and copy to the other buffer after
|
||||||
|
uint8_t *v86buf = (uintptr_t)buffer >= 0x20000 && (uintptr_t)buffer <= 0x2F000 ?
|
||||||
|
buffer :
|
||||||
|
(uint8_t*)0x20000;
|
||||||
|
|
||||||
// TODO Do error handling
|
// TODO Do error handling
|
||||||
if (!useCHS) {
|
if (!useCHS) {
|
||||||
// LBA Read
|
// LBA Read
|
||||||
|
1
helper.c
1
helper.c
@ -53,6 +53,7 @@ uint32_t OpenVol(VOLINFO *vi) {
|
|||||||
uint8_t pactive, ptype;
|
uint8_t pactive, ptype;
|
||||||
uint32_t pstart, psize;
|
uint32_t pstart, psize;
|
||||||
pstart = DFS_GetPtnStart(0, diskReadBuf, 0, &pactive, &ptype, &psize);
|
pstart = DFS_GetPtnStart(0, diskReadBuf, 0, &pactive, &ptype, &psize);
|
||||||
|
if (pstart == -1) return -1;
|
||||||
return DFS_GetVolInfo(0, diskReadBuf, pstart, vi);
|
return DFS_GetVolInfo(0, diskReadBuf, pstart, vi);
|
||||||
}
|
}
|
||||||
uint32_t OpenDir(uint8_t *path, VOLINFO *vi, DIRINFO *di) {
|
uint32_t OpenDir(uint8_t *path, VOLINFO *vi, DIRINFO *di) {
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
#define BLOCKSHIFT 16 // blockSize = 1 << blockShift
|
#define BLOCKSHIFT 16 // blockSize = 1 << blockShift
|
||||||
#define MAXFILESIZE 0x80000000 // 2GB
|
#define MAXFILESIZE 0x80000000 // 2GB
|
||||||
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
|
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
|
||||||
uint16_t writtenMap[TOTALBLOCKS] __attribute__((section(".progbss")));;
|
uint16_t writtenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));;
|
||||||
uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".progbss")));;
|
uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));;
|
||||||
// NOTE This is linked at the end of program BSS section,
|
// NOTE This is linked at the end of program BSS section,
|
||||||
// so that it can be expanded without telling C how much
|
// so that it can be expanded without telling C how much
|
||||||
// it actually needs
|
// it actually needs
|
||||||
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".proglatebss")));
|
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".hexlatebss")));
|
||||||
void HexEditor(uint8_t *path, VOLINFO *vi) {
|
void HexEditor(uint8_t *path, VOLINFO *vi) {
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
|
14
interrupt.c
14
interrupt.c
@ -95,9 +95,11 @@ extern uint16_t error_screen[80*50]; // defined in kernel.c
|
|||||||
extern uint16_t *ivt;
|
extern uint16_t *ivt;
|
||||||
extern void real_test();
|
extern void real_test();
|
||||||
extern void jmp_usermode_test();
|
extern void jmp_usermode_test();
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute__((__no_caller_saved_registers__))
|
||||||
|
__attribute__((__noreturn__))
|
||||||
extern void return_prev_task();
|
extern void return_prev_task();
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute__((__no_caller_saved_registers__))
|
||||||
|
__attribute__((__noreturn__))
|
||||||
extern void error_environment(); // defined in kernel.c
|
extern void error_environment(); // defined in kernel.c
|
||||||
extern uint32_t _gpf_eax_save;
|
extern uint32_t _gpf_eax_save;
|
||||||
#define VALID_FLAGS 0xDFF
|
#define VALID_FLAGS 0xDFF
|
||||||
@ -333,3 +335,11 @@ void setup_interrupts() {
|
|||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
void triple_fault() {
|
||||||
|
IDTR.size = 0;
|
||||||
|
asm volatile("lidt %0": : "m"(IDTR));
|
||||||
|
asm volatile("sti");
|
||||||
|
asm volatile("int $1");
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
7
kbd.c
7
kbd.c
@ -71,6 +71,13 @@ void keyboardHandler(struct interrupt_frame *frame) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute((__no_caller_saved_registers__))
|
||||||
|
void kbd_clear() {
|
||||||
|
_KBDWAIT = 0;
|
||||||
|
_LSTKEY_ASCII = 0;
|
||||||
|
_LSTKEY_SCAN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute((__no_caller_saved_registers__))
|
||||||
void kbd_wait() {
|
void kbd_wait() {
|
||||||
_KBDWAIT = 0;
|
_KBDWAIT = 0;
|
||||||
|
3
kbd.h
3
kbd.h
@ -5,6 +5,9 @@
|
|||||||
__attribute((__no_caller_saved_registers__))
|
__attribute((__no_caller_saved_registers__))
|
||||||
void kbd_wait();
|
void kbd_wait();
|
||||||
|
|
||||||
|
__attribute((__no_caller_saved_registers__))
|
||||||
|
void kbd_clear();
|
||||||
|
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute((__no_caller_saved_registers__))
|
||||||
uint8_t get_key();
|
uint8_t get_key();
|
||||||
|
|
||||||
|
149
kernel.c
149
kernel.c
@ -10,6 +10,7 @@
|
|||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "progs.h"
|
#include "progs.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
|
|
||||||
@ -63,15 +64,6 @@ uint32_t get_cr4() {
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern char _loadusercode, _usercode, _eusercode;
|
|
||||||
void LoadUser() {
|
|
||||||
// Put Usermode code in proper place based on linker
|
|
||||||
char *s = &_loadusercode;
|
|
||||||
char *d = &_usercode;
|
|
||||||
while (d < &_eusercode)
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern char _edata, _v86code, _ev86code, _bstart, _bend;
|
extern char _edata, _v86code, _ev86code, _bstart, _bend;
|
||||||
void setup_binary() {
|
void setup_binary() {
|
||||||
// Put V86 code in proper place based on linker
|
// Put V86 code in proper place based on linker
|
||||||
@ -80,26 +72,11 @@ void setup_binary() {
|
|||||||
while (d < &_ev86code)
|
while (d < &_ev86code)
|
||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
|
|
||||||
LoadUser();
|
|
||||||
|
|
||||||
// Clear BSS area
|
// Clear BSS area
|
||||||
for (d = &_bstart; d < &_bend; d++)
|
for (d = &_bstart; d < &_bend; d++)
|
||||||
*d = 0;
|
*d = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern char _bprogstart, _bprogend;
|
|
||||||
// NOTE This is linked at the same place
|
|
||||||
// as the load address of usermode code,
|
|
||||||
// so things linked with bss here *must not*
|
|
||||||
// call usermode code at the same place
|
|
||||||
void ClearProgBss() {
|
|
||||||
// TODO Make sure there's no weird alignment stuff,
|
|
||||||
// although more BSS should always come after this
|
|
||||||
// ideally.
|
|
||||||
for (uint32_t *d = (uint32_t*)&_bprogstart; d < (uint32_t*)&_bprogend; d++)
|
|
||||||
*d = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t error_screen[80*50]; // 50-line VGA screen of error content
|
uint16_t error_screen[80*50]; // 50-line VGA screen of error content
|
||||||
|
|
||||||
extern uint16_t *ivt;
|
extern uint16_t *ivt;
|
||||||
@ -124,9 +101,11 @@ void ensure_v86env() {
|
|||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute__((__no_caller_saved_registers__))
|
||||||
|
__attribute__((__noreturn__))
|
||||||
extern void return_prev_task();
|
extern void return_prev_task();
|
||||||
__attribute((__no_caller_saved_registers__))
|
__attribute__((__no_caller_saved_registers__))
|
||||||
|
__attribute__((__noreturn__))
|
||||||
void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32_t stack3, uint32_t stack4, uint32_t stack5) {
|
void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32_t stack3, uint32_t stack4, uint32_t stack5) {
|
||||||
ensure_v86env();
|
ensure_v86env();
|
||||||
setup_interrupts(); // just in case
|
setup_interrupts(); // just in case
|
||||||
@ -172,7 +151,7 @@ void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32
|
|||||||
uint32_t GetFreeStack() {
|
uint32_t GetFreeStack() {
|
||||||
uint32_t stack;
|
uint32_t stack;
|
||||||
asm volatile("mov %%esp,%%eax":"=a"(stack));
|
asm volatile("mov %%esp,%%eax":"=a"(stack));
|
||||||
stack = ((stack - 0x4000) / 0x1000) * 0x1000;
|
stack = ((stack - 0x2000) / 0x1000) * 0x1000;
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,12 +233,18 @@ void RestoreVGA() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t fileCount, fileOffset;
|
int32_t fileCount, fileOffset;
|
||||||
DIRENT *entries = (DIRENT*)0x400000;
|
// We store dir entries in usermode space,
|
||||||
|
// which is nice because there's nothing after,
|
||||||
|
// but it does mean we need to reload the dir
|
||||||
|
// after every task called. This might be fine,
|
||||||
|
// since the task might have modified the directory.
|
||||||
|
extern char _USERMODE;
|
||||||
|
DIRENT *const DirEntries = (DIRENT*)&_USERMODE;
|
||||||
#define MAXDISPFILES 16
|
#define MAXDISPFILES 16
|
||||||
void PrintFileList(uint16_t *vga) {
|
void PrintFileList(uint16_t *vga) {
|
||||||
uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
|
uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
|
||||||
for (int i = 0; (i + fileOffset) < fileCount && i < MAXDISPFILES; i++) {
|
for (int i = 0; (i + fileOffset) < fileCount && i < MAXDISPFILES; i++) {
|
||||||
DIRENT *de = &entries[i + fileOffset];
|
DIRENT *de = &DirEntries[i + fileOffset];
|
||||||
for (int i = 0; i < 11 && de->name[i]; i++) {
|
for (int i = 0; i < 11 && de->name[i]; i++) {
|
||||||
if (i == 8) { *(uint8_t*)vga_text = ' '; vga_text++; } // space for 8.3
|
if (i == 8) { *(uint8_t*)vga_text = ' '; vga_text++; } // space for 8.3
|
||||||
*(uint8_t *)vga_text = de->name[i];
|
*(uint8_t *)vga_text = de->name[i];
|
||||||
@ -323,7 +308,7 @@ void FileSelect() {
|
|||||||
OpenVol(&vi);
|
OpenVol(&vi);
|
||||||
current_path[current_path_end] = 0;
|
current_path[current_path_end] = 0;
|
||||||
OpenDir(current_path, &vi, &di);
|
OpenDir(current_path, &vi, &di);
|
||||||
GetFileList(entries, &fileCount, INT32_MAX, &vi, &di);
|
GetFileList(DirEntries, &fileCount, INT32_MAX, &vi, &di);
|
||||||
reload = 0;
|
reload = 0;
|
||||||
}
|
}
|
||||||
if (fileHovered >= fileCount) {
|
if (fileHovered >= fileCount) {
|
||||||
@ -365,23 +350,22 @@ void FileSelect() {
|
|||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_P:
|
case KEY_P:
|
||||||
if (IsDir(&entries[fileHovered])) break;
|
if (IsDir(&DirEntries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 2, current_path, &vi);
|
create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 2, current_path, &vi);
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_X:
|
case KEY_X:
|
||||||
if (IsDir(&entries[fileHovered])) break;
|
if (IsDir(&DirEntries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
ClearProgBss();
|
|
||||||
create_child(GetFreeStack(), (uintptr_t)HexEditor, 2, current_path, &vi);
|
create_child(GetFreeStack(), (uintptr_t)HexEditor, 2, current_path, &vi);
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_T:
|
case KEY_T:
|
||||||
if (IsDir(&entries[fileHovered])) break;
|
if (IsDir(&DirEntries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
//TextViewTest(path, &vi);
|
//TextViewTest(path, &vi);
|
||||||
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 2, current_path, &vi);
|
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 2, current_path, &vi);
|
||||||
RestoreVGA();
|
RestoreVGA();
|
||||||
@ -389,9 +373,9 @@ void FileSelect() {
|
|||||||
break;
|
break;
|
||||||
case KEY_O:
|
case KEY_O:
|
||||||
case 0x9C: // enter release
|
case 0x9C: // enter release
|
||||||
if (IsDir(&entries[fileHovered])) {
|
if (IsDir(&DirEntries[fileHovered])) {
|
||||||
uint8_t tmp_path[80];
|
uint8_t tmp_path[80];
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path);
|
File83ToPath((char*)DirEntries[fileHovered].name, (char*)tmp_path);
|
||||||
if ((*(uint32_t*)tmp_path & 0xffff) == ('.' | 0x0000)) {
|
if ((*(uint32_t*)tmp_path & 0xffff) == ('.' | 0x0000)) {
|
||||||
// Current dir, do nothing
|
// Current dir, do nothing
|
||||||
break;
|
break;
|
||||||
@ -425,6 +409,45 @@ void FileSelect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemRun() {
|
||||||
|
uint16_t *vga_text = (word *)0xb8000;
|
||||||
|
RestoreVGA();
|
||||||
|
DrawScreen((uint16_t*)0xb8000);
|
||||||
|
|
||||||
|
// Check for FAT partition
|
||||||
|
{
|
||||||
|
VOLINFO vi;
|
||||||
|
// TODO Check partitions beyond 0
|
||||||
|
while (OpenVol(&vi)) {
|
||||||
|
vga_text = &((word*)0xb8000)[80*4 + 2];
|
||||||
|
vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
|
||||||
|
vga_text = &((word*)0xb8000)[80*5 + 2];
|
||||||
|
vga_text += printStr("Press R to retry.", vga_text);
|
||||||
|
for (;(get_scancode() & 0xff) != KEY_R;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
create_child(GetFreeStack(), (uintptr_t)FileSelect, 0);
|
||||||
|
// should never return, so if it does,
|
||||||
|
// we have an error
|
||||||
|
{
|
||||||
|
union V86Regs_t regs;
|
||||||
|
FARPTR v86_entry = i386LinearToFp(v86TextMode);
|
||||||
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
|
}
|
||||||
|
RestoreVGA();
|
||||||
|
DrawScreen((uint16_t*)0xb8000);
|
||||||
|
vga_text = &((word*)0xb8000)[80*4 + 2];
|
||||||
|
vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
|
||||||
|
vga_text = &((word*)0xb8000)[80*5 + 2];
|
||||||
|
vga_text += printStr("Press R to retry.", vga_text);
|
||||||
|
for (;(get_scancode() & 0xff) != KEY_R;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((__noreturn__))
|
||||||
|
extern void triple_fault();
|
||||||
uint32_t kernel_check = 0x12345678;
|
uint32_t kernel_check = 0x12345678;
|
||||||
void start() {
|
void start() {
|
||||||
word *vga_text = (word *)0xb8000;
|
word *vga_text = (word *)0xb8000;
|
||||||
@ -471,46 +494,26 @@ void start() {
|
|||||||
//vga_text += printStr("Y ", vga_text);
|
//vga_text += printStr("Y ", vga_text);
|
||||||
//enable_sse();
|
//enable_sse();
|
||||||
|
|
||||||
setup_binary();
|
|
||||||
|
|
||||||
// edit
|
|
||||||
setup_interrupts();
|
|
||||||
setup_tss();
|
|
||||||
init_paging();
|
|
||||||
//print_flags();
|
//print_flags();
|
||||||
vga_text += printStr("CR0:", vga_text);
|
vga_text += printStr("CR0:", vga_text);
|
||||||
vga_text += printDword(get_cr0(), vga_text);
|
vga_text += printDword(get_cr0(), vga_text);
|
||||||
vga_text++;
|
vga_text++;
|
||||||
//print_cr3();
|
//print_cr3();
|
||||||
//print_cr4();
|
//print_cr4();
|
||||||
backup_ivtbios();
|
|
||||||
|
|
||||||
//vga_text = &((word *)0xb8000)[160];
|
// Setup system
|
||||||
//vga_text += printStr("Press T for tests, or any key to continue... ", vga_text);
|
setup_binary();
|
||||||
//uint8_t key = get_key();
|
setup_interrupts();
|
||||||
//if (key == 't' || key == 'T')
|
setup_tss();
|
||||||
// create_child(GetFreeStack(), (uintptr_t)RunTests, 0);
|
init_paging();
|
||||||
RestoreVGA();
|
backup_ivtbios();
|
||||||
DrawScreen((uint16_t*)0xb8000);
|
InitDisk();
|
||||||
uint32_t stack;
|
|
||||||
asm volatile("mov %%esp,%%eax":"=a"(stack));
|
create_child(GetFreeStack(), (uintptr_t)SystemRun, 0);
|
||||||
stack = ((stack - 0x4000) / 0x1000) * 0x1000;
|
// If this returns, something is *very* wrong, reboot the system
|
||||||
for (;;) {
|
// TODO Maybe try to recover?
|
||||||
create_child(stack, (uintptr_t)FileSelect, 0);
|
|
||||||
// should never return, so if it does,
|
// Triple fault
|
||||||
// we have an error
|
triple_fault();
|
||||||
{
|
|
||||||
union V86Regs_t regs;
|
|
||||||
FARPTR v86_entry = i386LinearToFp(v86TextMode);
|
|
||||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
|
||||||
}
|
|
||||||
RestoreVGA();
|
|
||||||
DrawScreen((uint16_t*)0xb8000);
|
|
||||||
vga_text = &((word*)0xb8000)[80*4 + 2];
|
|
||||||
vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
|
|
||||||
vga_text = &((word*)0xb8000)[80*5 + 2];
|
|
||||||
vga_text += printStr("Press R to retry.", vga_text);
|
|
||||||
for (;(get_scancode() & 0xff) != KEY_R;);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
link.ld
36
link.ld
@ -3,14 +3,15 @@ ENTRY(entry)
|
|||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0x100000;
|
. = 0x100000;
|
||||||
|
_USERMODE = 0x400000;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text);
|
*(.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data);
|
|
||||||
*(.data*);
|
*(.data*);
|
||||||
|
*(.data);
|
||||||
*(.rodata);
|
*(.rodata);
|
||||||
*(.rodata*);
|
*(.rodata*);
|
||||||
_edata = .;
|
_edata = .;
|
||||||
@ -19,29 +20,30 @@ SECTIONS {
|
|||||||
.realmode 0x4000 :
|
.realmode 0x4000 :
|
||||||
AT ( _edata )
|
AT ( _edata )
|
||||||
{ _v86code = .; *(.v86); _ev86code = .; }
|
{ _v86code = .; *(.v86); _ev86code = .; }
|
||||||
|
|
||||||
. = _edata + SIZEOF(.realmode);
|
. = _edata + SIZEOF(.realmode);
|
||||||
.thing : { _loadusercode = .; }
|
|
||||||
|
|
||||||
.usermode 0x400000 : AT(_loadusercode) {
|
|
||||||
_usercode = .; *(.user); _eusercode = .;
|
|
||||||
}
|
|
||||||
.bss 0x400000 (NOLOAD) : AT(_loadusercode + SIZEOF(.usermode)) {
|
|
||||||
_bprogstart = .;
|
|
||||||
*(.progbss);
|
|
||||||
*(.progbss*);
|
|
||||||
_bprogend = .;
|
|
||||||
*(.proglatebss);
|
|
||||||
*(.proglatebss*);
|
|
||||||
}
|
|
||||||
|
|
||||||
. = ADDR(.data) + SIZEOF(.data) + SIZEOF(.realmode) + SIZEOF(.usermode);
|
|
||||||
|
|
||||||
.bss : ALIGN(0x1000)
|
.bss : ALIGN(0x1000)
|
||||||
{
|
{
|
||||||
_bstart = .; *(.bss); *(.bss*) _bend = .;
|
_bstart = .; *(.bss); *(.bss*) _bend = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bss _USERMODE (NOLOAD) : AT(_bend) {
|
||||||
|
_bhexstart = .;
|
||||||
|
*(.hexbss);
|
||||||
|
*(.hexbss*);
|
||||||
|
_bhexend = .;
|
||||||
|
*(.hexlatebss);
|
||||||
|
*(.hexlatebss*);
|
||||||
|
}
|
||||||
|
.bss _USERMODE (NOLOAD) : AT(_bend) {
|
||||||
|
_btextstart = .;
|
||||||
|
*(.textbss);
|
||||||
|
*(.textbss*);
|
||||||
|
_btextend = .;
|
||||||
|
*(.textlatebss);
|
||||||
|
*(.textlatebss*);
|
||||||
|
}
|
||||||
|
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.note*)
|
*(.note*)
|
||||||
*(.comment*)
|
*(.comment*)
|
||||||
|
184
progs.c
184
progs.c
@ -1,193 +1,15 @@
|
|||||||
#include "progs.h"
|
#include "progs.h"
|
||||||
|
|
||||||
void TextViewTest(uint8_t *path, VOLINFO *vi) {
|
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
|
||||||
uint32_t fileLen;
|
|
||||||
uint8_t *diskReadBuf = (uint8_t *)0x500000;
|
|
||||||
{
|
|
||||||
uint32_t err;
|
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
|
||||||
FILEINFO fi;
|
|
||||||
err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
|
|
||||||
if (err) {
|
|
||||||
vga_text += printStr("Open Error: ", vga_text);
|
|
||||||
printDword(err, vga_text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// file too large
|
|
||||||
if (fi.filelen > 0x300000) {
|
|
||||||
vga_text += printStr("File too large.", vga_text);
|
|
||||||
kbd_wait();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DFS_Seek(&fi, 0, scratch);
|
|
||||||
if (fi.pointer != 0) {
|
|
||||||
vga_text += printStr("Seek Error", vga_text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = DFS_ReadFile(&fi, scratch, diskReadBuf, &fileLen, fi.filelen);
|
|
||||||
if (err && err != DFS_EOF) {
|
|
||||||
vga_text += printStr("Read Error: ", vga_text);
|
|
||||||
printDword(err, vga_text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t *lineOffsets = (uint32_t *)0x400000;
|
|
||||||
uint32_t lastLine;
|
|
||||||
{
|
|
||||||
char nl;
|
|
||||||
uint8_t c = 0x0A; // start with a pretend newline
|
|
||||||
uint32_t line = -1; // start a pretend line behind
|
|
||||||
for (int32_t o = -1; o < (int32_t)fileLen; c = diskReadBuf[++o]) {
|
|
||||||
// newline
|
|
||||||
if (c == 0x0A) {
|
|
||||||
lineOffsets[++line] = o;
|
|
||||||
}
|
|
||||||
// file too large
|
|
||||||
if ((uintptr_t)&lineOffsets[line] >= 0x4FFFFC) {
|
|
||||||
vga_text += printStr("File too large.", vga_text);
|
|
||||||
kbd_wait();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastLine = line;
|
|
||||||
}
|
|
||||||
uint32_t currLine = 0;
|
|
||||||
char cont = 1;
|
|
||||||
uint32_t screenSize = 80*25;
|
|
||||||
char redraw = 1;
|
|
||||||
uint32_t linesOnScreen = 0;
|
|
||||||
for (;cont;) {
|
|
||||||
if (redraw) {
|
|
||||||
vga_text = (uint16_t *)0xb8000;
|
|
||||||
for (int i = 0; i < screenSize; i++)
|
|
||||||
vga_text[i] = 0x0f00;
|
|
||||||
char pathBuff[22];
|
|
||||||
trimPath((char*)path, pathBuff, sizeof(pathBuff));
|
|
||||||
vga_text += printStr(pathBuff, vga_text);
|
|
||||||
vga_text += 2;
|
|
||||||
vga_text += printDec(currLine, vga_text);
|
|
||||||
vga_text += printChar('/', vga_text);
|
|
||||||
vga_text += printDec(lastLine, vga_text);
|
|
||||||
vga_text += printStr(" Scroll: Up/Down PgUp/PgDown Home/End", vga_text);
|
|
||||||
{
|
|
||||||
const char prnt[] = "Exit: E";
|
|
||||||
vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)+1];
|
|
||||||
vga_text += printStr((char*)prnt, vga_text);
|
|
||||||
}
|
|
||||||
for (vga_text = &((uint16_t*)0xb8000)[84]; vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text += 80)
|
|
||||||
*(uint8_t*)vga_text = '|';
|
|
||||||
vga_text = &((uint16_t*)0xb8000)[0];
|
|
||||||
uint32_t lineOff = 6;
|
|
||||||
uint8_t c = 0x0A; // start with a pretend newline
|
|
||||||
uint32_t line = currLine - 1; // start a pretend line behind
|
|
||||||
int32_t o = lineOffsets[currLine]; // the real or fake newline on previous line
|
|
||||||
linesOnScreen = screenSize/80;
|
|
||||||
for (; o < (int32_t)fileLen && vga_text < &((uint16_t*)0xb8000)[screenSize]; c = diskReadBuf[++o]) {
|
|
||||||
// newline
|
|
||||||
if (c == 0x0A) {
|
|
||||||
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
|
||||||
line++;
|
|
||||||
{
|
|
||||||
uint16_t *vga_tmp = vga_text;
|
|
||||||
uint16_t decTmp[11];
|
|
||||||
char cnt = printDec(line, decTmp);
|
|
||||||
char off = cnt <= 4 ? 0 : cnt - 4;
|
|
||||||
vga_tmp += 4 - (cnt - off);
|
|
||||||
for (int i = off; i < cnt; i++, vga_tmp++)
|
|
||||||
*(uint8_t*)vga_tmp = (uint8_t)decTmp[i];
|
|
||||||
}
|
|
||||||
vga_text += 6;
|
|
||||||
lineOff = 6;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*(uint8_t*)vga_text = c;
|
|
||||||
vga_text++;
|
|
||||||
lineOff++;
|
|
||||||
if (lineOff == 80) { // last char
|
|
||||||
vga_text += 6;
|
|
||||||
lineOff = 6;
|
|
||||||
linesOnScreen--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
redraw = 0;
|
|
||||||
}
|
|
||||||
uint16_t key = get_scancode();
|
|
||||||
union V86Regs_t regs;
|
|
||||||
FARPTR v86_entry;
|
|
||||||
switch (key & 0xff) {
|
|
||||||
case KEY_DOWN: // down
|
|
||||||
if (currLine < lastLine && lineOffsets[currLine+1] < fileLen) {
|
|
||||||
currLine++;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_UP: // up
|
|
||||||
if ((currLine > 0 && lineOffsets[currLine-1] < fileLen) || currLine == 1) {
|
|
||||||
currLine--;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_PGDOWN:
|
|
||||||
if (currLine+(linesOnScreen/2) <= lastLine && lineOffsets[currLine+(linesOnScreen/2)] < fileLen) {
|
|
||||||
currLine += (linesOnScreen/2);
|
|
||||||
redraw = 1;
|
|
||||||
} else goto end;
|
|
||||||
break;
|
|
||||||
case KEY_PGUP:
|
|
||||||
if (currLine > (linesOnScreen/2) && lineOffsets[currLine-(linesOnScreen/2)] < fileLen) {
|
|
||||||
currLine -= (linesOnScreen/2);
|
|
||||||
redraw = 1;
|
|
||||||
} else if (currLine <= (linesOnScreen/2)) {
|
|
||||||
currLine = 0;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_HOME: home:
|
|
||||||
if (currLine != 0) {
|
|
||||||
currLine = 0;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_END: end:
|
|
||||||
if (currLine != lastLine) {
|
|
||||||
currLine = lastLine;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_E: // e
|
|
||||||
cont = 0;
|
|
||||||
break;
|
|
||||||
case KEY_F2:
|
|
||||||
if (screenSize != 80*25) {
|
|
||||||
SetVideo25Lines();
|
|
||||||
SetCursorDisabled();
|
|
||||||
screenSize = 80*25;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_F5:
|
|
||||||
if (screenSize != 80*50) {
|
|
||||||
SetVideo50Lines();
|
|
||||||
SetCursorDisabled();
|
|
||||||
screenSize = 80*50;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 400000 - 700000 Usermode Code (3mB)
|
// 400000 - 700000 Usermode Code (3mB)
|
||||||
// 700000 - 800000 Usermode Stack (1mB)
|
// 700000 - 800000 Usermode Stack (1mB)
|
||||||
|
extern char _USERMODE;
|
||||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||||
void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
|
void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < 80*25; i++)
|
for (int i = 0; i < 80*25; i++)
|
||||||
vga_text[i] = 0x0f00;
|
vga_text[i] = 0x0f00;
|
||||||
uint32_t successcount;
|
uint32_t successcount;
|
||||||
uint8_t *diskReadBuf = (uint8_t *)0x400000;
|
uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
|
||||||
{
|
{
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
@ -227,7 +49,7 @@ void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
|
|||||||
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
||||||
vga_text += printStr("Press any key to run.", vga_text);
|
vga_text += printStr("Press any key to run.", vga_text);
|
||||||
kbd_wait();
|
kbd_wait();
|
||||||
uint32_t res = create_user_child(0x800000, 0x400000, 0);
|
uint32_t res = create_user_child(0x800000, (uintptr_t)&_USERMODE, 0);
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
regs.w.ax = 3; // text mode
|
regs.w.ax = 3; // text mode
|
||||||
V8086Int(0x10, ®s);
|
V8086Int(0x10, ®s);
|
||||||
|
89
tests.c
89
tests.c
@ -13,18 +13,21 @@ void TestV86() {
|
|||||||
regs.d.eax = 0x66666666;
|
regs.d.eax = 0x66666666;
|
||||||
FARPTR v86_entry = i386LinearToFp(v86Test);
|
FARPTR v86_entry = i386LinearToFp(v86Test);
|
||||||
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
|
uint16_t *vga_text = (uint16_t *)0xb8000 + (80*2);
|
||||||
|
vga_text += printStr("Done.", vga_text);
|
||||||
}
|
}
|
||||||
extern char _loadusercode, _usercode, _eusercode;
|
extern char _USERMODE;
|
||||||
|
extern char _binary_usermode_bin_start, _binary_usermode_bin_end;
|
||||||
void ReloadUser() {
|
void ReloadUser() {
|
||||||
// Put Usermode code in proper place based on linker
|
// Put Usermode code in proper place based on linker
|
||||||
char *s = &_loadusercode;
|
char *s = &_binary_usermode_bin_start;
|
||||||
char *d = &_usercode;
|
char *d = (char *)&_USERMODE;
|
||||||
while (d < &_eusercode)
|
while (s < &_binary_usermode_bin_end)
|
||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
}
|
}
|
||||||
char TestUser() {
|
char TestUser() {
|
||||||
ReloadUser();
|
ReloadUser();
|
||||||
char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)user_test, 0);
|
char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)&_USERMODE, 0);
|
||||||
if ((uintptr_t)vga != 0xA0000) {
|
if ((uintptr_t)vga != 0xA0000) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -34,24 +37,40 @@ char TestUser() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void TestDiskRead() {
|
void TestDiskRead() {
|
||||||
//vga_text += printStr("Starting Disk Read... ", vga_text);
|
|
||||||
union V86Regs_t regs;
|
|
||||||
char *diskReadBuf = (char *)0x20000;
|
char *diskReadBuf = (char *)0x20000;
|
||||||
v86disk_addr_packet.transfer_buffer =
|
v86disk_addr_packet.transfer_buffer =
|
||||||
(uintptr_t)diskReadBuf & 0x000F |
|
(uintptr_t)diskReadBuf & 0x000F |
|
||||||
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
|
||||||
|
v86disk_addr_packet.start_block = 0;
|
||||||
|
v86disk_addr_packet.blocks = 2;
|
||||||
|
union V86Regs_t regs;
|
||||||
|
kbd_clear();
|
||||||
|
for (;;) {
|
||||||
regs.h.ah = 0x42;
|
regs.h.ah = 0x42;
|
||||||
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
FARPTR v86_entry = i386LinearToFp(v86DiskOp);
|
||||||
enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < (80*25)/2; i++) {
|
for (int i = 0; i < 25; i++) {
|
||||||
printByte(diskReadBuf[i], &vga_text[i*2]);
|
uint16_t *vga_line = &vga_text[i*80];
|
||||||
|
for (int j = 0; j < 26; j++) {
|
||||||
|
printByte(diskReadBuf[i*26 + j], &vga_line[j*2]);
|
||||||
|
*(uint8_t*)&vga_line[j + (26*2)+1] = diskReadBuf[i*26 + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint16_t scan = get_scancode();
|
||||||
|
if ((scan & 0xff) == KEY_PGUP) {
|
||||||
|
if(v86disk_addr_packet.start_block > 0) v86disk_addr_packet.start_block--;
|
||||||
|
} else if ((scan & 0xff) == KEY_PGDOWN)
|
||||||
|
v86disk_addr_packet.start_block++;
|
||||||
|
else if (scan & 0xff00) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extern uint32_t _gpf_eax_save;
|
extern uint32_t _gpf_eax_save;
|
||||||
extern uint32_t _gpf_eflags_save;
|
extern uint32_t _gpf_eflags_save;
|
||||||
void TestCHS() {
|
void TestCHS() {
|
||||||
uint16_t *vga_text = (uint16_t*)0xb8000;
|
uint16_t *vga_text = (uint16_t*)0xb8000;
|
||||||
|
for (int i = 0; i < 80*25; i++)
|
||||||
|
vga_text[i] = 0x0f00;
|
||||||
printStr("CHS Test ", vga_text);
|
printStr("CHS Test ", vga_text);
|
||||||
// CHS Read
|
// CHS Read
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
@ -175,41 +194,50 @@ void TestFAT() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RunTests() {
|
void RunTests() {
|
||||||
|
char doTests = 1;
|
||||||
uint16_t *vga_text = (uint16_t*)0xb8000;
|
uint16_t *vga_text = (uint16_t*)0xb8000;
|
||||||
|
uint8_t key;
|
||||||
|
for (char l = 1;l;) {
|
||||||
|
if (doTests) {
|
||||||
|
vga_text = (uint16_t*)0xb8000;
|
||||||
for (int i = 0; i < 80*25; i++)
|
for (int i = 0; i < 80*25; i++)
|
||||||
vga_text[i] = 0x1f00;
|
vga_text[i] = 0x1f00;
|
||||||
uint8_t key;
|
|
||||||
vga_text += printStr("V86 Test... ", vga_text);
|
vga_text += printStr("V86 Test... ", vga_text);
|
||||||
//asm ("xchgw %bx, %bx");
|
//asm ("xchgw %bx, %bx");
|
||||||
TestV86(); // has int 3 wait in v86
|
TestV86(); // has int 3 wait in v86
|
||||||
vga_text = (uint16_t *)0xb8000 + (80*3);
|
vga_text = (uint16_t *)0xb8000 + (80*3);
|
||||||
vga_text += printStr("Done. Press 'N' for next test.", vga_text);
|
vga_text += printStr("Press 'N' for next test.", vga_text);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
key = get_key();
|
key = get_key();
|
||||||
if (key == 'N' || key == 'n') break;
|
if (key == 'N' || key == 'n') break;
|
||||||
*vga_text = (*vga_text & 0xFF00) | key;
|
*vga_text = (*vga_text & 0xFF00) | key;
|
||||||
vga_text++;
|
vga_text++;
|
||||||
}
|
}
|
||||||
char userResult = TestUser();
|
if (TestUser()) {
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
regs.w.ax = 3; // text mode
|
regs.w.ax = 3; // text mode
|
||||||
V8086Int(0x10, ®s);
|
V8086Int(0x10, ®s);
|
||||||
vga_text = (uint16_t *)0xb8000 + (80*5);
|
vga_text = (uint16_t *)0xb8000 + (80*5);
|
||||||
printStr("Press any key to continue.", vga_text);
|
|
||||||
if (userResult) {
|
|
||||||
// Usermode returned wrong value
|
|
||||||
printStr("Usermode test failed! Press any key to continue.", vga_text);
|
printStr("Usermode test failed! Press any key to continue.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
} else {
|
||||||
|
kbd_wait();
|
||||||
|
union V86Regs_t regs;
|
||||||
|
regs.w.ax = 3; // text mode
|
||||||
|
V8086Int(0x10, ®s);
|
||||||
|
}
|
||||||
|
doTests = 0;
|
||||||
}
|
}
|
||||||
kbd_wait();
|
|
||||||
TestCHS();
|
|
||||||
kbd_wait();
|
|
||||||
TestDiskRead();
|
|
||||||
kbd_wait();
|
|
||||||
TestFAT();
|
|
||||||
|
|
||||||
|
vga_text = &((uint16_t*)0xB8000)[80*14];
|
||||||
|
vga_text += printStr("Press E for a flagrant system error. ", vga_text);
|
||||||
|
vga_text = &((uint16_t*)0xB8000)[80*15];
|
||||||
|
vga_text += printStr("Press D for disk tests. ", vga_text);
|
||||||
vga_text = &((uint16_t*)0xB8000)[80*16];
|
vga_text = &((uint16_t*)0xB8000)[80*16];
|
||||||
vga_text += printStr("Press E for a flagrant system error. Press C to continue... ", vga_text);
|
vga_text += printStr("Press R to repeat tests. ", vga_text);
|
||||||
for (char l = 1;l;) { switch (key = get_key()) {
|
vga_text = &((uint16_t*)0xB8000)[80*17];
|
||||||
|
vga_text += printStr("Press C to continue... ", vga_text);
|
||||||
|
switch (key = get_key()) {
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
// flagrant system error
|
// flagrant system error
|
||||||
@ -220,10 +248,23 @@ void RunTests() {
|
|||||||
// continue
|
// continue
|
||||||
l = 0;
|
l = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
// disk tests
|
||||||
|
TestCHS();
|
||||||
|
kbd_wait();
|
||||||
|
TestDiskRead();
|
||||||
|
TestFAT();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
doTests = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*vga_text = (*vga_text & 0xFF00) | key;
|
*vga_text = (*vga_text & 0xFF00) | key;
|
||||||
vga_text++;
|
vga_text++;
|
||||||
break;
|
break;
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
238
textedit.c
Normal file
238
textedit.c
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#include "progs.h"
|
||||||
|
|
||||||
|
#define MAXFILESIZE 0x300000 // 3MB
|
||||||
|
#define MAXLINES 100000
|
||||||
|
#define BLOCKSIZE 0x1000
|
||||||
|
#define BLOCKMASK 0xfff
|
||||||
|
#define BLOCKSHIFT 12
|
||||||
|
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
|
||||||
|
uintptr_t lineOffsets[MAXLINES] __attribute__((section(".textbss")));;
|
||||||
|
uintptr_t lineLengths[MAXLINES] __attribute__((section(".textbss")));;
|
||||||
|
uint8_t editedBlocks[TOTALBLOCKS] __attribute__((section(".textbss")));;
|
||||||
|
uint8_t fileBuffer[MAXFILESIZE]
|
||||||
|
__attribute__((aligned(0x1000)))
|
||||||
|
__attribute__((section(".textlatebss")));
|
||||||
|
void TextViewTest(uint8_t *path, VOLINFO *vi) {
|
||||||
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
|
uint32_t fileLen;
|
||||||
|
{
|
||||||
|
uint32_t err;
|
||||||
|
uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
|
FILEINFO fi;
|
||||||
|
err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
|
||||||
|
if (err) {
|
||||||
|
vga_text += printStr("Open Error: ", vga_text);
|
||||||
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// file too large
|
||||||
|
if (fi.filelen > MAXFILESIZE) {
|
||||||
|
vga_text += printStr("File too large.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DFS_Seek(&fi, 0, scratch);
|
||||||
|
if (fi.pointer != 0) {
|
||||||
|
vga_text += printStr("Seek Error", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = DFS_ReadFile(&fi, scratch, fileBuffer, &fileLen, fi.filelen);
|
||||||
|
if (err && err != DFS_EOF) {
|
||||||
|
vga_text += printStr("Read Error: ", vga_text);
|
||||||
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t lastLine;
|
||||||
|
{
|
||||||
|
char nl;
|
||||||
|
uint8_t c = 0x0A; // start with a pretend newline
|
||||||
|
uint32_t line = -1; // start a pretend line behind
|
||||||
|
uint32_t lineLen = 0;
|
||||||
|
for (int32_t o = -1; o < (int32_t)fileLen; lineLen++, c = fileBuffer[++o]) {
|
||||||
|
// newline
|
||||||
|
if (c == 0x0A) {
|
||||||
|
lineOffsets[++line] = o;
|
||||||
|
lineLengths[line] = lineLen > 0 ? lineLen : 1;
|
||||||
|
lineLen = 0;
|
||||||
|
}
|
||||||
|
// file too large
|
||||||
|
if (line >= MAXLINES) {
|
||||||
|
vga_text += printStr("File too large.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineLengths[line] = lineLen;
|
||||||
|
lastLine = line;
|
||||||
|
}
|
||||||
|
uint32_t currLine = 0;
|
||||||
|
char cont = 1;
|
||||||
|
uint32_t screenSize = 80*25;
|
||||||
|
char redraw = 1;
|
||||||
|
uint32_t linesOnScreen = 0;
|
||||||
|
uint32_t cursorLine = 0;
|
||||||
|
uint32_t cursorLineOffset = 0;
|
||||||
|
char cursorChange = 0;
|
||||||
|
for (;cont;) {
|
||||||
|
if (cursorLine > lastLine) {
|
||||||
|
cursorLine = lastLine;
|
||||||
|
cursorLineOffset = lineLengths[lastLine] - 2;
|
||||||
|
cursorChange = 1;
|
||||||
|
}
|
||||||
|
if (lineLengths[cursorLine+1] == 1 && cursorLineOffset == 0){}
|
||||||
|
else if (cursorLineOffset >= lineLengths[cursorLine+1] - 1) {
|
||||||
|
cursorLineOffset = 0;
|
||||||
|
cursorLine++;
|
||||||
|
cursorChange = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redraw || cursorChange) {
|
||||||
|
vga_text = (uint16_t *)0xb8000;
|
||||||
|
for (int i = 0; i < screenSize; i++)
|
||||||
|
vga_text[i] = 0x0f00;
|
||||||
|
char pathBuff[22];
|
||||||
|
trimPath((char*)path, pathBuff, sizeof(pathBuff));
|
||||||
|
vga_text += printStr(pathBuff, vga_text);
|
||||||
|
vga_text += 2;
|
||||||
|
vga_text += printDec(currLine, vga_text);
|
||||||
|
vga_text += printChar('/', vga_text);
|
||||||
|
vga_text += printDec(lastLine, vga_text);
|
||||||
|
vga_text += printStr(" Scroll: Up/Down PgUp/PgDown Home/End", vga_text);
|
||||||
|
{
|
||||||
|
const char prnt[] = "Exit: F1";
|
||||||
|
vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)+1];
|
||||||
|
vga_text += printStr((char*)prnt, vga_text);
|
||||||
|
}
|
||||||
|
for (vga_text = &((uint16_t*)0xb8000)[84]; vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text += 80)
|
||||||
|
*(uint8_t*)vga_text = '|';
|
||||||
|
vga_text = &((uint16_t*)0xb8000)[0];
|
||||||
|
uint32_t screenLineOff = 6;
|
||||||
|
uint32_t lineOffset = 0;
|
||||||
|
uint8_t c = 0x0A; // start with a pretend newline
|
||||||
|
uint32_t line = currLine - 1; // start a pretend line behind
|
||||||
|
int32_t o = lineOffsets[currLine]; // the real or fake newline on previous line
|
||||||
|
linesOnScreen = screenSize/80;
|
||||||
|
for (; o < (int32_t)fileLen && vga_text < &((uint16_t*)0xb8000)[screenSize]; c = fileBuffer[++o]) {
|
||||||
|
// newline
|
||||||
|
if (c == 0x0A) {
|
||||||
|
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
||||||
|
line++;
|
||||||
|
lineOffset = 0;
|
||||||
|
{
|
||||||
|
uint16_t *vga_tmp = vga_text;
|
||||||
|
uint16_t decTmp[11];
|
||||||
|
char cnt = printDec(line, decTmp);
|
||||||
|
char off = cnt <= 4 ? 0 : cnt - 4;
|
||||||
|
vga_tmp += 4 - (cnt - off);
|
||||||
|
for (int i = off; i < cnt; i++, vga_tmp++)
|
||||||
|
*(uint8_t*)vga_tmp = (uint8_t)decTmp[i];
|
||||||
|
}
|
||||||
|
vga_text += 6;
|
||||||
|
screenLineOff = 6;
|
||||||
|
if (cursorLine == line && cursorLineOffset == lineOffset) {
|
||||||
|
((uint8_t*)vga_text)[1] = 0xf0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*(uint8_t*)vga_text = c;
|
||||||
|
if (cursorLine == line && cursorLineOffset == lineOffset) {
|
||||||
|
((uint8_t*)vga_text)[1] = 0xf0;
|
||||||
|
}
|
||||||
|
lineOffset++;
|
||||||
|
vga_text++;
|
||||||
|
screenLineOff++;
|
||||||
|
if (screenLineOff == 80) { // last char
|
||||||
|
vga_text += 6;
|
||||||
|
screenLineOff = 6;
|
||||||
|
linesOnScreen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = 0;
|
||||||
|
}
|
||||||
|
uint16_t key = get_scancode();
|
||||||
|
union V86Regs_t regs;
|
||||||
|
FARPTR v86_entry;
|
||||||
|
switch (key & 0xff) {
|
||||||
|
/*case KEY_DOWN: // down
|
||||||
|
if (currLine < lastLine && lineOffsets[currLine+1] < fileLen) {
|
||||||
|
currLine++;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_UP: // up
|
||||||
|
if ((currLine > 0 && lineOffsets[currLine-1] < fileLen) || currLine == 1) {
|
||||||
|
currLine--;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;*/
|
||||||
|
case KEY_DOWN:
|
||||||
|
cursorLine++;
|
||||||
|
cursorChange = 1;
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
if (cursorLine > 0) cursorLine--;
|
||||||
|
cursorChange = 1;
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
if (cursorLineOffset > 0) cursorLineOffset--;
|
||||||
|
cursorChange = 1;
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
cursorLineOffset++;
|
||||||
|
cursorChange = 1;
|
||||||
|
break;
|
||||||
|
case KEY_PGDOWN:
|
||||||
|
if (currLine+(linesOnScreen/2) <= lastLine && lineOffsets[currLine+(linesOnScreen/2)] < fileLen) {
|
||||||
|
currLine += (linesOnScreen/2);
|
||||||
|
redraw = 1;
|
||||||
|
} else goto end;
|
||||||
|
break;
|
||||||
|
case KEY_PGUP:
|
||||||
|
if (currLine > (linesOnScreen/2) && lineOffsets[currLine-(linesOnScreen/2)] < fileLen) {
|
||||||
|
currLine -= (linesOnScreen/2);
|
||||||
|
redraw = 1;
|
||||||
|
} else if (currLine <= (linesOnScreen/2)) {
|
||||||
|
currLine = 0;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_HOME: home:
|
||||||
|
if (currLine != 0) {
|
||||||
|
currLine = 0;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_END: end:
|
||||||
|
if (currLine != lastLine) {
|
||||||
|
currLine = lastLine;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_F1:
|
||||||
|
cont = 0;
|
||||||
|
break;
|
||||||
|
case KEY_F2:
|
||||||
|
if (screenSize != 80*25) {
|
||||||
|
SetVideo25Lines();
|
||||||
|
SetCursorDisabled();
|
||||||
|
screenSize = 80*25;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_F5:
|
||||||
|
if (screenSize != 80*50) {
|
||||||
|
SetVideo50Lines();
|
||||||
|
SetCursorDisabled();
|
||||||
|
screenSize = 80*50;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
[SECTION .user]
|
[BITS 32]
|
||||||
|
[ORG 0x400000]
|
||||||
global user_test
|
global user_test
|
||||||
user_test:
|
user_test:
|
||||||
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
||||||
|
192
v86.nasm
192
v86.nasm
@ -4,7 +4,83 @@ global v86Interrupt
|
|||||||
v86Interrupt:
|
v86Interrupt:
|
||||||
int 0x00
|
int 0x00
|
||||||
int 0x30
|
int 0x30
|
||||||
jmp $
|
ud2
|
||||||
|
|
||||||
|
global v86TransFlag
|
||||||
|
v86TransFlag:
|
||||||
|
push cs
|
||||||
|
pop es
|
||||||
|
mov ax, 0x13
|
||||||
|
int 0x10
|
||||||
|
mov ax,0x1012
|
||||||
|
xor bx,bx
|
||||||
|
mov cx,5
|
||||||
|
mov dx,.c
|
||||||
|
int 0x10
|
||||||
|
push 0xa000
|
||||||
|
pop es
|
||||||
|
xor di,di
|
||||||
|
xor ax,ax
|
||||||
|
.loop:
|
||||||
|
mov cx, 12800
|
||||||
|
rep stosb
|
||||||
|
inc ax
|
||||||
|
cmp ax,5
|
||||||
|
jl .loop
|
||||||
|
int 0x30
|
||||||
|
ud2
|
||||||
|
.c: db `\0263>=*.\?\?\?=*.\0263>`
|
||||||
|
|
||||||
|
global v86VideoInt
|
||||||
|
v86VideoInt:
|
||||||
|
int 0x10
|
||||||
|
int 0x30
|
||||||
|
ud2
|
||||||
|
|
||||||
|
global v86DiskOp
|
||||||
|
v86DiskOp:
|
||||||
|
xor bx, bx ; TODO fix assuming we're in first 64k
|
||||||
|
mov ds, bx
|
||||||
|
mov dl, 0x80 ; TODO get this from BIOS or something
|
||||||
|
mov si, v86disk_addr_packet ; ds:si
|
||||||
|
int 0x13
|
||||||
|
jc .err
|
||||||
|
int 0x30
|
||||||
|
.err:
|
||||||
|
ud2
|
||||||
|
global v86disk_addr_packet
|
||||||
|
v86disk_addr_packet:
|
||||||
|
db 0x10, 0x00 ; size, reserved
|
||||||
|
dw 0x1 ; blocks
|
||||||
|
dd 0x23000000 ; transfer buffer 0x23000
|
||||||
|
dq 0x1 ; start block
|
||||||
|
|
||||||
|
global v86DiskGetGeometry
|
||||||
|
v86DiskGetGeometry:
|
||||||
|
mov ah, 8
|
||||||
|
mov dl, 0x80
|
||||||
|
int 0x13
|
||||||
|
movzx eax, ch
|
||||||
|
shl eax, 16
|
||||||
|
mov al, cl
|
||||||
|
mov ah, dh
|
||||||
|
int 0x30
|
||||||
|
ud2
|
||||||
|
|
||||||
|
global v86DiskReadCHS
|
||||||
|
v86DiskReadCHS:
|
||||||
|
push 0x2000
|
||||||
|
pop es
|
||||||
|
int 0x13
|
||||||
|
int 0x30
|
||||||
|
ud2
|
||||||
|
|
||||||
|
global v86TextMode
|
||||||
|
v86TextMode:
|
||||||
|
mov ax, 0x3
|
||||||
|
int 0x10
|
||||||
|
int 0x30
|
||||||
|
ud2
|
||||||
|
|
||||||
real_hexprint:
|
real_hexprint:
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
@ -36,94 +112,48 @@ ret
|
|||||||
|
|
||||||
global v86Test
|
global v86Test
|
||||||
v86Test:
|
v86Test:
|
||||||
mov ax, 0xb814
|
mov ax, (0xB8000 + (80*2)) >> 4
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov di, 20
|
mov di, 0
|
||||||
|
mov word es:[di+0], 0x1f00 | 'S'
|
||||||
|
mov word es:[di+2], 0x1f00 | 'S'
|
||||||
|
mov word es:[di+4], 0x1f00 | ':'
|
||||||
|
add di, 6
|
||||||
|
mov ax, ss
|
||||||
|
call real_printword
|
||||||
|
add di, 2
|
||||||
|
mov word es:[di+0], 0x1f00 | 'S'
|
||||||
|
mov word es:[di+2], 0x1f00 | 'P'
|
||||||
|
mov word es:[di+4], 0x1f00 | ':'
|
||||||
|
add di, 6
|
||||||
mov ax, sp
|
mov ax, sp
|
||||||
call real_printword
|
call real_printword
|
||||||
add di, 2
|
add di, 2
|
||||||
|
mov word es:[di+0], 0x1f00 | 'D'
|
||||||
|
mov word es:[di+2], 0x1f00 | 'S'
|
||||||
|
mov word es:[di+4], 0x1f00 | ':'
|
||||||
|
add di, 6
|
||||||
mov ax, ds
|
mov ax, ds
|
||||||
call real_printword
|
call real_printword
|
||||||
add di, 2
|
add di, 2
|
||||||
|
mov word es:[di+0], 0x1f00 | 'C'
|
||||||
|
mov word es:[di+2], 0x1f00 | 'S'
|
||||||
|
mov word es:[di+4], 0x1f00 | ':'
|
||||||
|
add di, 6
|
||||||
mov ax, cs
|
mov ax, cs
|
||||||
call real_printword
|
call real_printword
|
||||||
int 3
|
add di, 2
|
||||||
|
mov ax, cs
|
||||||
|
mov ds, ax
|
||||||
|
mov si, .testStr
|
||||||
|
mov ah, 0x1f
|
||||||
|
mov cx, .testStr_end - .testStr
|
||||||
|
.print:
|
||||||
|
lodsb
|
||||||
|
stosw
|
||||||
|
loop .print
|
||||||
|
int 3 ; wait for key
|
||||||
int 0x30 ; exit
|
int 0x30 ; exit
|
||||||
jmp $
|
|
||||||
|
|
||||||
global v86TransFlag
|
|
||||||
v86TransFlag:
|
|
||||||
push cs
|
|
||||||
pop es
|
|
||||||
mov ax, 0x13
|
|
||||||
int 0x10
|
|
||||||
mov ax,0x1012
|
|
||||||
xor bx,bx
|
|
||||||
mov cx,5
|
|
||||||
mov dx,.c
|
|
||||||
int 0x10
|
|
||||||
push 0xa000
|
|
||||||
pop es
|
|
||||||
xor di,di
|
|
||||||
xor ax,ax
|
|
||||||
.loop:
|
|
||||||
mov cx, 12800
|
|
||||||
rep stosb
|
|
||||||
inc ax
|
|
||||||
cmp ax,5
|
|
||||||
jl .loop
|
|
||||||
int 0x30
|
|
||||||
jmp $
|
|
||||||
.c: db `\0263>=*.\?\?\?=*.\0263>`
|
|
||||||
|
|
||||||
global v86TextMode
|
|
||||||
v86TextMode:
|
|
||||||
mov ax, 0x3
|
|
||||||
int 0x10
|
|
||||||
int 0x30
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
global v86VideoInt
|
|
||||||
v86VideoInt:
|
|
||||||
int 0x10
|
|
||||||
int 0x30
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
global v86DiskOp
|
|
||||||
v86DiskOp:
|
|
||||||
xor bx, bx ; TODO fix assuming we're in first 64k
|
|
||||||
mov ds, bx
|
|
||||||
mov dl, 0x80 ; TODO get this from BIOS or something
|
|
||||||
mov si, v86disk_addr_packet ; ds:si
|
|
||||||
int 0x13
|
|
||||||
jc .err
|
|
||||||
int 0x30
|
|
||||||
.err:
|
|
||||||
ud2
|
|
||||||
jmp $
|
|
||||||
global v86disk_addr_packet
|
|
||||||
v86disk_addr_packet:
|
|
||||||
db 0x10, 0x00 ; size, reserved
|
|
||||||
dw 0x1 ; blocks
|
|
||||||
dd 0x23000000 ; transfer buffer 0x23000
|
|
||||||
dq 0x1 ; start block
|
|
||||||
|
|
||||||
global v86DiskGetGeometry
|
|
||||||
v86DiskGetGeometry:
|
|
||||||
mov ah, 8
|
|
||||||
mov dl, 0x80
|
|
||||||
int 0x13
|
|
||||||
movzx eax, ch
|
|
||||||
shl eax, 16
|
|
||||||
mov al, cl
|
|
||||||
mov ah, dh
|
|
||||||
int 0x30
|
|
||||||
ud2
|
|
||||||
|
|
||||||
global v86DiskReadCHS
|
|
||||||
v86DiskReadCHS:
|
|
||||||
push 0x2000
|
|
||||||
pop es
|
|
||||||
int 0x13
|
|
||||||
int 0x30
|
|
||||||
ud2
|
ud2
|
||||||
|
.testStr: db "PRESS ANY KEY"
|
||||||
|
.testStr_end:
|
||||||
|
Loading…
Reference in New Issue
Block a user