2022-09-14 16:50:44 -05:00
|
|
|
#include <stdint.h>
|
|
|
|
|
2023-02-14 23:48:11 -06:00
|
|
|
#include "file.h"
|
2023-02-17 06:21:43 -06:00
|
|
|
#include "fs.h"
|
2022-09-14 21:54:59 -05:00
|
|
|
#include "print.h"
|
|
|
|
#include "interrupt.h"
|
2023-02-05 19:57:06 -06:00
|
|
|
#include "kbd.h"
|
2022-09-19 16:06:01 -05:00
|
|
|
#include "tss.h"
|
2023-01-31 21:26:43 -06:00
|
|
|
#include "paging.h"
|
2023-02-02 14:52:26 -06:00
|
|
|
#include "v86defs.h"
|
2023-02-02 21:40:39 -06:00
|
|
|
#include "tests.h"
|
2023-02-06 02:27:33 -06:00
|
|
|
#include "progs.h"
|
|
|
|
#include "helper.h"
|
2023-02-12 00:42:14 -06:00
|
|
|
#include "disk.h"
|
2022-09-14 21:54:59 -05:00
|
|
|
|
|
|
|
typedef unsigned short word;
|
2022-09-14 16:50:44 -05:00
|
|
|
|
|
|
|
char check_apic() {
|
|
|
|
uint32_t eax, ebx, ecx, edx;
|
|
|
|
asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
|
|
|
|
return (edx & (1 << 9)) != 0;
|
|
|
|
}
|
|
|
|
char check_sse() {
|
|
|
|
uint32_t eax, ebx, ecx, edx;
|
|
|
|
asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
|
|
|
|
return (edx & (1 << 25)) != 0;
|
|
|
|
}
|
2023-02-08 11:38:35 -06:00
|
|
|
char check_cmov() {
|
|
|
|
uint32_t eax, ebx, ecx, edx;
|
|
|
|
asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
|
|
|
|
return (edx & (1 << 15)) != 0;
|
|
|
|
}
|
2022-09-14 16:50:44 -05:00
|
|
|
|
|
|
|
void enable_sse() {
|
|
|
|
asm volatile(
|
|
|
|
"mov %%cr0, %%eax\n"
|
|
|
|
"and $0xFFFB, %%ax\n"
|
|
|
|
"or $0x2, %%ax\n"
|
|
|
|
"mov %%eax, %%cr0\n"
|
|
|
|
"mov %%cr4, %%eax\n"
|
|
|
|
"or $0x600, %%ax\n"
|
|
|
|
"mov %%eax, %%cr4\n"
|
|
|
|
: : : "%eax"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-02-01 14:18:27 -06:00
|
|
|
uint32_t get_flags() {
|
2022-09-14 16:50:44 -05:00
|
|
|
uint32_t flags;
|
|
|
|
asm volatile("pushfd\npop %%eax":"=a"(flags));
|
2023-02-01 14:18:27 -06:00
|
|
|
return flags;
|
2022-09-14 16:50:44 -05:00
|
|
|
}
|
2023-02-01 14:18:27 -06:00
|
|
|
uint32_t get_cr0() {
|
2022-09-14 16:50:44 -05:00
|
|
|
uint32_t reg;
|
|
|
|
asm volatile("mov %%cr0, %%eax":"=a"(reg));
|
2023-02-01 14:18:27 -06:00
|
|
|
return reg;
|
2022-09-14 16:50:44 -05:00
|
|
|
}
|
2023-02-01 14:18:27 -06:00
|
|
|
uint32_t get_cr3() {
|
2022-09-14 16:50:44 -05:00
|
|
|
uint32_t reg;
|
|
|
|
asm volatile("mov %%cr3, %%eax":"=a"(reg));
|
2023-02-01 14:18:27 -06:00
|
|
|
return reg;
|
2022-09-14 16:50:44 -05:00
|
|
|
}
|
2023-02-01 14:18:27 -06:00
|
|
|
uint32_t get_cr4() {
|
2022-09-14 16:50:44 -05:00
|
|
|
uint32_t reg;
|
|
|
|
asm volatile("mov %%cr4, %%eax":"=a"(reg));
|
2023-02-01 14:18:27 -06:00
|
|
|
return reg;
|
2022-09-14 16:50:44 -05:00
|
|
|
}
|
|
|
|
|
2023-02-04 18:51:09 -06:00
|
|
|
extern char _edata, _v86code, _ev86code, _bstart, _bend;
|
2023-01-31 21:26:43 -06:00
|
|
|
void setup_binary() {
|
|
|
|
// Put V86 code in proper place based on linker
|
|
|
|
char *s = &_edata;
|
|
|
|
char *d = &_v86code;
|
2023-02-01 20:42:05 -06:00
|
|
|
while (d < &_ev86code)
|
|
|
|
*d++ = *s++;
|
2023-01-31 21:26:43 -06:00
|
|
|
|
|
|
|
// Clear BSS area
|
|
|
|
for (d = &_bstart; d < &_bend; d++)
|
|
|
|
*d = 0;
|
|
|
|
}
|
|
|
|
|
2023-02-01 20:42:05 -06:00
|
|
|
uint16_t error_screen[80*50]; // 50-line VGA screen of error content
|
|
|
|
|
|
|
|
extern uint16_t *ivt;
|
|
|
|
uint16_t ivt_bkup[0x200];
|
|
|
|
uint8_t bios_bkup[0x40000];
|
|
|
|
void backup_ivtbios() {
|
|
|
|
for (int i = 0; i < 0x200; i++)
|
|
|
|
ivt_bkup[i] = ivt[i];
|
|
|
|
for (int i = 0; i < 0x40000; i++)
|
|
|
|
bios_bkup[i] = ((uint8_t*)0xC0000)[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// This should only be used during fault handling, as it is expensive
|
|
|
|
void ensure_v86env() {
|
|
|
|
for (int i = 0; i < 0x200; i++)
|
|
|
|
ivt[i] = ivt_bkup[i];
|
|
|
|
for (int i = 0; i < 0x40000; i++)
|
|
|
|
((uint8_t*)0xC0000)[i] = bios_bkup[i];
|
|
|
|
char *s = &_edata;
|
|
|
|
char *d = &_v86code;
|
|
|
|
while (d < &_ev86code)
|
|
|
|
*d++ = *s++;
|
|
|
|
}
|
|
|
|
|
2023-02-13 18:23:33 -06:00
|
|
|
uint32_t _ERRORCODE = 0;
|
|
|
|
__attribute__((__no_caller_saved_registers__))
|
|
|
|
uint32_t check_error_code() {
|
|
|
|
uint32_t v = _ERRORCODE;
|
|
|
|
_ERRORCODE = 0;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2023-02-12 00:42:14 -06:00
|
|
|
__attribute__((__no_caller_saved_registers__))
|
|
|
|
__attribute__((__noreturn__))
|
2023-02-06 03:07:15 -06:00
|
|
|
extern void return_prev_task();
|
2023-02-12 00:42:14 -06:00
|
|
|
__attribute__((__no_caller_saved_registers__))
|
|
|
|
__attribute__((__noreturn__))
|
2023-02-07 23:53:13 -06:00
|
|
|
void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32_t stack3, uint32_t stack4, uint32_t stack5) {
|
2023-02-01 20:42:05 -06:00
|
|
|
ensure_v86env();
|
2023-02-07 23:53:13 -06:00
|
|
|
setup_interrupts(); // just in case
|
2023-02-07 18:52:17 -06:00
|
|
|
for (int i = 0; i < 80*50; i++)
|
|
|
|
if (!(error_screen[i] & 0xFF00))
|
|
|
|
error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF);
|
2023-02-02 14:52:26 -06:00
|
|
|
union V86Regs_t regs;
|
2023-02-01 20:42:05 -06:00
|
|
|
FARPTR v86_entry = i386LinearToFp(v86TextMode);
|
2023-02-02 14:52:26 -06:00
|
|
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
2023-02-07 23:53:13 -06:00
|
|
|
char str0[] = "Oh noes!!! System error! ;c STKDMP:";
|
2023-02-06 03:07:15 -06:00
|
|
|
printStr(str0, &error_screen[80]);
|
2023-02-07 23:53:13 -06:00
|
|
|
uint16_t *tmp = &error_screen[80+sizeof(str0)-1];
|
|
|
|
tmp += printDword(stack0, tmp);
|
|
|
|
tmp++;
|
|
|
|
tmp += printDword(stack1, tmp);
|
|
|
|
tmp++;
|
|
|
|
tmp += printDword(stack2, tmp);
|
|
|
|
tmp = &error_screen[80*2+sizeof(str0)-1];
|
|
|
|
tmp += printDword(stack3, tmp);
|
|
|
|
tmp++;
|
|
|
|
tmp += printDword(stack4, tmp);
|
|
|
|
tmp++;
|
|
|
|
tmp += printDword(stack5, tmp);
|
|
|
|
printStr("Press E for a fun recovery :3", &error_screen[80*2]);
|
|
|
|
printStr("Press R to return to previous task", &error_screen[80*3]);
|
2023-02-01 20:42:05 -06:00
|
|
|
uint16_t *vga_text = ((uint16_t*)0xB8000);
|
|
|
|
for (int i = 0; i < 80*50; i++)
|
|
|
|
vga_text[i] = error_screen[i];
|
2023-02-06 03:07:15 -06:00
|
|
|
for(;;) {
|
|
|
|
uint8_t key = get_scancode() & 0xff;
|
2023-02-10 03:57:44 -06:00
|
|
|
if (key == KEY_E) {
|
|
|
|
v86_entry = i386LinearToFp(v86TransFlag);
|
|
|
|
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
|
2023-02-07 18:52:17 -06:00
|
|
|
}
|
2023-02-10 03:57:44 -06:00
|
|
|
if (key == KEY_R) break;
|
2023-02-06 03:07:15 -06:00
|
|
|
}
|
2023-02-10 03:57:44 -06:00
|
|
|
// reset error screen
|
|
|
|
for (int i = 0; i < (80*50)/2; i++)
|
|
|
|
((uint32_t*)error_screen)[i] = 0x0f000f00;
|
2023-02-13 18:23:33 -06:00
|
|
|
_ERRORCODE = -1;
|
2023-02-10 03:57:44 -06:00
|
|
|
return_prev_task();
|
2023-02-01 20:42:05 -06:00
|
|
|
}
|
|
|
|
|
2023-02-10 03:42:53 -06:00
|
|
|
uint32_t GetFreeStack() {
|
|
|
|
uint32_t stack;
|
|
|
|
asm volatile("mov %%esp,%%eax":"=a"(stack));
|
2023-02-12 00:42:14 -06:00
|
|
|
stack = ((stack - 0x2000) / 0x1000) * 0x1000;
|
2023-02-10 03:42:53 -06:00
|
|
|
return stack;
|
|
|
|
}
|
|
|
|
|
2022-09-14 16:50:44 -05:00
|
|
|
/*
|
|
|
|
Real Mode Accessible (First MB)
|
2022-09-19 16:06:01 -05:00
|
|
|
00000 - 00400 IVT (1kB)
|
|
|
|
00400 - 01000 Unused (3kB)
|
2023-01-31 21:26:43 -06:00
|
|
|
01000 - 04000 Free (12kB)
|
2023-02-02 14:52:26 -06:00
|
|
|
04000 - 07C00 V86 Code (15kB)
|
|
|
|
07C00 - 08000 Boot & V86 Code (512B)
|
2023-02-17 01:41:30 -06:00
|
|
|
08000 - 20000 Free (96kB)
|
2023-01-31 21:26:43 -06:00
|
|
|
20000 - 30000 Disk Buffer (64kB)
|
2023-02-17 01:41:30 -06:00
|
|
|
30000 - 40000 V86 Data (64kB)
|
|
|
|
40000 - 80000 Free (256kB)
|
|
|
|
80000 - 90000 V86 Stack (64kB)
|
2022-09-19 16:06:01 -05:00
|
|
|
90000 - A0000 Free (64kB)
|
2023-01-31 21:26:43 -06:00
|
|
|
A0000 - C0000 VGA (128kB)
|
|
|
|
C0000 - FFFFF BIOS Area (256kB)
|
2022-09-14 16:50:44 -05:00
|
|
|
Protected Only (1MB+)
|
2023-01-31 21:26:43 -06:00
|
|
|
100000 - 200000 Kernel Code (1mB)
|
|
|
|
200000 - 200080 TSS (128B)
|
|
|
|
200080 - 202080 TSS IOMAP (8kB)
|
2023-02-14 23:48:11 -06:00
|
|
|
202080 - 208000 Free (~24kB)
|
|
|
|
208000 - 240000 Kernel File Stack (224kB)
|
|
|
|
240000 - 280000 Active Filesystems (128kB)
|
2023-02-10 01:06:42 -06:00
|
|
|
280000 - 300000 Disk Cache (512kB)
|
2022-09-19 16:06:01 -05:00
|
|
|
300000 - 310000 Task Stack (64kB)
|
|
|
|
310000 - 320000 Interrupt Stack (64kB)
|
2024-01-07 22:33:27 -06:00
|
|
|
320000 - 400000 Free (896kB)
|
|
|
|
400000 - 700000 Free (3mB)
|
|
|
|
700000 - 800000 Kernel Stack (1mB)
|
|
|
|
800000 - F00000 Usermode Code (7mB)
|
|
|
|
F00000 - 1000000 Usermode Stack (1mB)
|
2022-09-14 16:50:44 -05:00
|
|
|
*/
|
2023-02-13 18:23:33 -06:00
|
|
|
|
2023-02-10 04:45:47 -06:00
|
|
|
void DrawScreen(uint16_t *vga) {
|
|
|
|
uint16_t *vga_text = vga;
|
2023-02-02 21:40:39 -06:00
|
|
|
// clear screen
|
|
|
|
for (int i = 0; i < 80*25; i++)
|
|
|
|
vga_text[i] = 0x1f00;
|
|
|
|
// draw border
|
|
|
|
for (int c = 1; c < 79; c++) {
|
|
|
|
vga_text[c] = 0x1fc4; // top line
|
|
|
|
vga_text[(2*80)+c] = 0x1fc4; // 3rd line
|
|
|
|
vga_text[(24*80)+c] = 0x1fc4; // bottom line
|
2022-09-21 17:14:11 -05:00
|
|
|
}
|
2023-02-02 21:40:39 -06:00
|
|
|
for (int l = 1; l < 24; l++) {
|
|
|
|
vga_text[80*l] = 0x1fb3;
|
|
|
|
vga_text[(80*l)+79] = 0x1fb3;
|
2022-09-21 17:14:11 -05:00
|
|
|
}
|
2023-02-02 21:40:39 -06:00
|
|
|
vga_text[0] = 0x1fda;
|
|
|
|
vga_text[79] = 0x1fbf;
|
|
|
|
vga_text[2*80] = 0x1fc3;
|
|
|
|
vga_text[2*80+79] = 0x1fb4;
|
|
|
|
vga_text[24*80] = 0x1fc0;
|
|
|
|
vga_text[24*80+79] = 0x1fd9;
|
|
|
|
// name
|
|
|
|
vga_text[80+34] = 0x1f00 | '-';
|
|
|
|
vga_text[80+35] = 0x1f00 | ' ';
|
|
|
|
vga_text[80+36] = 0x1f00 | 'L';
|
|
|
|
vga_text[80+37] = 0x1f00 | 'u';
|
|
|
|
vga_text[80+38] = 0x1f00 | 'c';
|
|
|
|
vga_text[80+39] = 0x1f00 | 'i';
|
|
|
|
vga_text[80+40] = 0x1f00 | 'a';
|
|
|
|
vga_text[80+41] = 0x1f00 | 'O';
|
|
|
|
vga_text[80+42] = 0x1f00 | 'S';
|
|
|
|
vga_text[80+43] = 0x1f00 | ' ';
|
|
|
|
vga_text[80+44] = 0x1f00 | '-';
|
|
|
|
}
|
2022-09-21 17:14:11 -05:00
|
|
|
|
2023-02-10 04:24:29 -06:00
|
|
|
void SetPalette() {
|
|
|
|
union V86Regs_t regs;
|
|
|
|
regs.w.bx = 1; // index
|
|
|
|
regs.h.dh = 0x3D;
|
|
|
|
regs.h.ch = 0x2A;
|
|
|
|
regs.h.cl = 0x2E;
|
|
|
|
regs.w.ax = 0x1010; // set DAC color register
|
|
|
|
V8086Int(0x10, ®s);
|
|
|
|
}
|
|
|
|
// NOTE Does not set text mode
|
|
|
|
void RestoreVGA() {
|
|
|
|
SetVideo25Lines();
|
|
|
|
SetCursorDisabled();
|
|
|
|
SetPalette();
|
|
|
|
}
|
|
|
|
|
2023-02-10 22:17:03 -06:00
|
|
|
int32_t fileCount, fileOffset;
|
2023-02-12 00:42:14 -06:00
|
|
|
extern char _USERMODE;
|
2024-01-07 22:33:27 -06:00
|
|
|
dirent *const DirEntries = (dirent*)0x400000;
|
2023-02-10 22:17:03 -06:00
|
|
|
#define MAXDISPFILES 16
|
2023-02-10 04:45:47 -06:00
|
|
|
void PrintFileList(uint16_t *vga) {
|
|
|
|
uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
|
2023-02-10 22:17:03 -06:00
|
|
|
for (int i = 0; (i + fileOffset) < fileCount && i < MAXDISPFILES; i++) {
|
2023-02-14 23:48:11 -06:00
|
|
|
dirent *de = &DirEntries[i + fileOffset];
|
|
|
|
de->name[de->namelen < 20 ? de->namelen : 20] = 0;
|
|
|
|
vga_text += printStr(de->name, vga_text);
|
2023-02-04 18:51:09 -06:00
|
|
|
vga_text += printStr(" ", vga_text);
|
2023-02-14 23:48:11 -06:00
|
|
|
vga_text += printDec(de->size, vga_text);
|
2023-02-04 18:51:09 -06:00
|
|
|
*(uint8_t*)vga_text++ = 'B';
|
2023-02-10 04:45:47 -06:00
|
|
|
vga_text = nextLine(vga_text, vga) + 3;
|
2023-02-04 18:51:09 -06:00
|
|
|
}
|
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
char IsDir(dirent *de) {
|
|
|
|
return de->type == FT_DIR;
|
2023-02-08 12:48:01 -06:00
|
|
|
}
|
2023-02-09 13:19:50 -06:00
|
|
|
void ScancodeTest() {
|
|
|
|
uint16_t *vga = (uint16_t*)0xb8000;
|
|
|
|
uint16_t scancode;
|
|
|
|
while(((scancode = get_scancode()) & 0xff) != KEY_F1) {
|
|
|
|
vga += printWord(scancode, vga);
|
|
|
|
vga++;
|
|
|
|
if ((uintptr_t)vga >= 0xb8000+80*25*2)
|
|
|
|
vga = (uint16_t*)0xb8000;
|
|
|
|
}
|
|
|
|
}
|
2023-02-06 03:55:13 -06:00
|
|
|
extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
2023-02-10 04:45:47 -06:00
|
|
|
uint16_t FileSelectScreen[80*25];
|
2023-02-17 06:21:43 -06:00
|
|
|
char ValidFilesystems[256];
|
2023-02-02 21:40:39 -06:00
|
|
|
void FileSelect() {
|
2023-02-17 06:21:43 -06:00
|
|
|
ActiveFilesystemBitmap(ValidFilesystems);
|
|
|
|
uint8_t currentFsId = 0;
|
2023-02-14 23:48:11 -06:00
|
|
|
char current_path[80];
|
2023-02-08 12:48:01 -06:00
|
|
|
uintptr_t current_path_end;
|
|
|
|
for (int i = 0; i < sizeof(current_path); i++)
|
|
|
|
current_path[i] = 0;
|
2023-02-17 06:21:43 -06:00
|
|
|
current_path[0] = '0';
|
|
|
|
current_path[1] = '/';
|
|
|
|
current_path_end = 2;
|
2023-02-02 21:40:39 -06:00
|
|
|
fileCount = 5;
|
2023-02-10 04:45:47 -06:00
|
|
|
uint16_t *vga_text = (uint16_t *)FileSelectScreen;
|
2023-02-10 22:17:03 -06:00
|
|
|
int32_t fileHovered = 0;
|
|
|
|
fileOffset = 0;
|
2023-02-04 18:51:09 -06:00
|
|
|
for (char reload = 1;;) {
|
2023-02-10 04:45:47 -06:00
|
|
|
DrawScreen(vga_text);
|
2023-02-08 12:48:01 -06:00
|
|
|
// Info line (4)
|
|
|
|
{
|
|
|
|
uint16_t *vga = &vga_text[80*4 + 79 - 24];
|
|
|
|
printStr("X to view in hex", vga);
|
|
|
|
vga += 80;
|
2023-02-09 13:19:50 -06:00
|
|
|
printStr("T to view as text", vga);
|
2023-02-08 12:48:01 -06:00
|
|
|
vga += 80;
|
|
|
|
printStr("P to load as program", vga);
|
|
|
|
vga += 80;
|
|
|
|
printStr("O to open directory", vga);
|
2023-02-09 13:19:50 -06:00
|
|
|
vga += 80;
|
2023-02-17 06:21:43 -06:00
|
|
|
printStr("S to switch volume", vga);
|
|
|
|
vga += 80;
|
2023-02-09 13:19:50 -06:00
|
|
|
printStr("F4 to run tests", vga);
|
2023-02-08 12:48:01 -06:00
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
printStr(current_path, &vga_text[80*4 + 2]);
|
2023-02-08 12:48:01 -06:00
|
|
|
for (int i = 2; i < 15; i++)
|
|
|
|
*(uint8_t*)&vga_text[80*5 + i] = '-';
|
2023-02-14 23:48:11 -06:00
|
|
|
DIR dir;
|
2023-02-04 18:51:09 -06:00
|
|
|
if (reload) {
|
2023-02-08 12:48:01 -06:00
|
|
|
current_path[current_path_end] = 0;
|
2023-02-14 23:48:11 -06:00
|
|
|
dir_open(&dir, current_path);
|
|
|
|
GetFileList(&dir, DirEntries, &fileCount, INT32_MAX);
|
2023-02-04 18:51:09 -06:00
|
|
|
reload = 0;
|
|
|
|
}
|
2023-02-10 22:17:03 -06:00
|
|
|
if (fileHovered >= fileCount) {
|
|
|
|
fileOffset = fileCount - MAXDISPFILES;
|
|
|
|
fileHovered = fileCount - 1;
|
|
|
|
}
|
|
|
|
if ((fileHovered - fileOffset) >= MAXDISPFILES)
|
|
|
|
fileOffset = fileHovered - MAXDISPFILES + 1;
|
|
|
|
else if ((fileHovered - fileOffset) < 0)
|
|
|
|
fileOffset = fileHovered;
|
2023-02-10 04:45:47 -06:00
|
|
|
PrintFileList(vga_text);
|
2023-02-10 22:17:03 -06:00
|
|
|
for (int i = 6; i < 24; i++) {
|
|
|
|
*(uint8_t*)&vga_text[80*i+2] = ' ';
|
2023-02-02 21:40:39 -06:00
|
|
|
}
|
2023-02-10 22:17:03 -06:00
|
|
|
*(uint8_t*)&vga_text[80*(6+(fileHovered-fileOffset))+2] = '>';
|
2023-02-10 04:45:47 -06:00
|
|
|
// Copy to real VGA
|
|
|
|
for (int i = 0; i < 80*25; i++)
|
|
|
|
((uint16_t*)0xb8000)[i] = vga_text[i];
|
2023-02-02 21:40:39 -06:00
|
|
|
uint16_t key = get_scancode();
|
2023-02-06 00:01:48 -06:00
|
|
|
uint8_t path[13];
|
2023-02-02 21:40:39 -06:00
|
|
|
switch (key & 0xff) { // scancode component
|
2023-02-09 13:19:50 -06:00
|
|
|
case KEY_DOWN: // down
|
2023-02-02 21:40:39 -06:00
|
|
|
fileHovered++;
|
2023-02-10 22:17:03 -06:00
|
|
|
if (fileHovered >= fileCount) { fileHovered = 0; fileOffset = 0; }
|
2023-02-02 21:40:39 -06:00
|
|
|
break;
|
2023-02-09 13:19:50 -06:00
|
|
|
case KEY_UP: // up
|
2023-02-02 21:40:39 -06:00
|
|
|
fileHovered--;
|
|
|
|
if (fileHovered < 0) fileHovered = fileCount - 1;
|
|
|
|
break;
|
2023-02-09 13:19:50 -06:00
|
|
|
case KEY_F4:
|
2023-02-10 03:42:53 -06:00
|
|
|
create_child(GetFreeStack(), (uintptr_t)RunTests, 0);
|
2023-02-10 04:24:29 -06:00
|
|
|
// Set Text mode, tests might return in gfx
|
|
|
|
{
|
|
|
|
union V86Regs_t regs;
|
|
|
|
regs.w.ax = 3;
|
|
|
|
V8086Int(0x10, ®s);
|
|
|
|
}
|
|
|
|
RestoreVGA();
|
2023-02-04 18:51:09 -06:00
|
|
|
reload = 1;
|
|
|
|
break;
|
2023-02-06 05:49:03 -06:00
|
|
|
case KEY_P:
|
2023-02-12 00:42:14 -06:00
|
|
|
if (IsDir(&DirEntries[fileHovered])) break;
|
2023-02-14 23:48:11 -06:00
|
|
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
|
|
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
|
|
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
2023-02-17 06:21:43 -06:00
|
|
|
create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 1, current_path);
|
2023-02-14 23:48:11 -06:00
|
|
|
current_path[current_path_end] = 0;
|
2023-02-10 04:24:29 -06:00
|
|
|
RestoreVGA();
|
2023-02-06 05:49:03 -06:00
|
|
|
reload = 1;
|
|
|
|
break;
|
2023-02-06 00:01:48 -06:00
|
|
|
case KEY_X:
|
2023-02-12 00:42:14 -06:00
|
|
|
if (IsDir(&DirEntries[fileHovered])) break;
|
2023-02-14 23:48:11 -06:00
|
|
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
|
|
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
|
|
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
2024-01-07 22:33:27 -06:00
|
|
|
{
|
|
|
|
// Give userspace mem (8MB)
|
|
|
|
uintptr_t process_page0 = add_pages(4|2|1);
|
|
|
|
uintptr_t process_page1 = add_pages(4|2|1);
|
|
|
|
asm("xchg %bx,%bx");
|
|
|
|
// Page blocks are 4MB
|
|
|
|
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
|
|
|
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
|
|
|
asm("xchg %bx,%bx");
|
|
|
|
create_child(GetFreeStack(), (uintptr_t)HexEditor, 1, current_path);
|
|
|
|
// Free userspace mem
|
|
|
|
free_pages(process_page0 >> 22);
|
|
|
|
free_pages(process_page1 >> 22);
|
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
current_path[current_path_end] = 0;
|
2023-02-10 04:24:29 -06:00
|
|
|
RestoreVGA();
|
2023-02-08 12:48:01 -06:00
|
|
|
reload = 1;
|
2023-02-04 18:51:09 -06:00
|
|
|
break;
|
2023-02-09 13:19:50 -06:00
|
|
|
case KEY_T:
|
2023-02-12 00:42:14 -06:00
|
|
|
if (IsDir(&DirEntries[fileHovered])) break;
|
2023-02-06 03:55:13 -06:00
|
|
|
//TextViewTest(path, &vi);
|
2023-02-14 23:48:11 -06:00
|
|
|
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
|
|
|
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
|
|
|
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
2024-01-07 22:33:27 -06:00
|
|
|
{
|
|
|
|
// Give userspace mem (8MB)
|
|
|
|
uintptr_t process_page0 = add_pages(4|2|1);
|
|
|
|
uintptr_t process_page1 = add_pages(4|2|1);
|
|
|
|
// Page blocks are 4MB
|
|
|
|
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
|
|
|
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
|
|
|
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 1, current_path);
|
|
|
|
// Free userspace mem
|
|
|
|
free_pages(process_page0 >> 22);
|
|
|
|
free_pages(process_page1 >> 22);
|
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
current_path[current_path_end] = 0;
|
2023-02-10 04:24:29 -06:00
|
|
|
RestoreVGA();
|
2023-02-06 00:01:48 -06:00
|
|
|
reload = 1;
|
|
|
|
break;
|
2023-02-08 12:48:01 -06:00
|
|
|
case KEY_O:
|
2023-02-09 13:19:50 -06:00
|
|
|
case 0x9C: // enter release
|
2023-02-12 00:42:14 -06:00
|
|
|
if (IsDir(&DirEntries[fileHovered])) {
|
2023-02-08 12:48:01 -06:00
|
|
|
uint8_t tmp_path[80];
|
2023-02-14 23:48:11 -06:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < DirEntries[fileHovered].namelen && i < sizeof(tmp_path)-1; i++)
|
|
|
|
tmp_path[i] = DirEntries[fileHovered].name[i];
|
|
|
|
tmp_path[i] = 0;
|
|
|
|
}
|
2023-02-08 12:48:01 -06:00
|
|
|
if ((*(uint32_t*)tmp_path & 0xffff) == ('.' | 0x0000)) {
|
|
|
|
// Current dir, do nothing
|
|
|
|
break;
|
|
|
|
} else if ((*(uint32_t*)tmp_path & 0xffffff) == ('.' | '.' << 8 | 0x000000)) {
|
|
|
|
// Up one directory
|
|
|
|
for (current_path_end--;current_path_end >= 1 && current_path[current_path_end - 1] != '/'; current_path_end--);
|
|
|
|
current_path[current_path_end] = 0;
|
|
|
|
reload = 1;
|
|
|
|
fileHovered = 0;
|
2023-02-10 22:17:03 -06:00
|
|
|
fileOffset = 0;
|
2023-02-08 12:48:01 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (int i = 0; (i + current_path_end) < sizeof(current_path); i++)
|
|
|
|
current_path[current_path_end + i] = tmp_path[i];
|
|
|
|
for (;current_path_end < sizeof(current_path) - 2 && current_path[current_path_end]; current_path_end++);
|
|
|
|
current_path[current_path_end] = '/';
|
|
|
|
current_path_end++;
|
|
|
|
current_path[current_path_end] = 0;
|
|
|
|
reload = 1;
|
|
|
|
fileHovered = 0;
|
2023-02-10 22:17:03 -06:00
|
|
|
fileOffset = 0;
|
2023-02-08 12:48:01 -06:00
|
|
|
}
|
|
|
|
break;
|
2023-02-17 06:21:43 -06:00
|
|
|
case KEY_S:
|
|
|
|
// Next filesystem TODO Support over 077 I'm so lazy right now
|
|
|
|
for (currentFsId = (currentFsId + 1) % 64; !ValidFilesystems[currentFsId]; currentFsId = (currentFsId + 1) % 64);
|
|
|
|
if (currentFsId < 8) {
|
|
|
|
current_path[0] = '0' + currentFsId;
|
|
|
|
current_path[1] = '/';
|
|
|
|
current_path[2] = 0;
|
|
|
|
current_path_end = 2;
|
|
|
|
} else {
|
|
|
|
current_path[0] = '0' + (currentFsId >> 3);
|
|
|
|
current_path[1] = '0' + (currentFsId & 7);
|
|
|
|
current_path[2] = '/';
|
|
|
|
current_path[3] = 0;
|
|
|
|
current_path_end = 3;
|
|
|
|
}
|
|
|
|
reload = 1;
|
|
|
|
fileHovered = 0;
|
|
|
|
fileOffset = 0;
|
|
|
|
break;
|
2023-02-09 13:19:50 -06:00
|
|
|
case KEY_F6:
|
|
|
|
ScancodeTest();
|
|
|
|
reload = 1;
|
|
|
|
break;
|
2023-02-02 21:40:39 -06:00
|
|
|
default:
|
|
|
|
break;
|
2022-09-21 17:14:11 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-07 22:33:27 -06:00
|
|
|
// TODO Move this somewhere else, maybe configurable & with timer handler
|
|
|
|
void PITPgrm() {
|
|
|
|
const uint32_t base_clk = 3579545;
|
|
|
|
const uint16_t reload_v = 1194;
|
|
|
|
// (base_clk / 3) / reload_v = ~999.31463Hz
|
|
|
|
|
|
|
|
// 32.32 Fixed point
|
|
|
|
const uint64_t irq_ms = (uint64_t)reload_v * 3000LL * ((1LL << 42) / (uint64_t)base_clk / (1LL << 10));
|
|
|
|
// irq_ms = 4294818000 (0xfffdb8d0)
|
|
|
|
// We don't actually use this here, but in handler.nasm
|
|
|
|
// for now, eventually this should be in C
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
"cli\n"
|
|
|
|
"movb $0b00110100, %%al\n"
|
|
|
|
"outb %%al, $0x43\n"
|
|
|
|
:::"%eax"
|
|
|
|
);
|
|
|
|
uint32_t clobber_eax;
|
|
|
|
asm volatile(
|
|
|
|
"outb %%al, $0x40\n"
|
|
|
|
"movb %%ah, %%al\n"
|
|
|
|
"outb %%al, $0x40\n"
|
|
|
|
"sti\n"
|
|
|
|
:"=a"(clobber_eax):"a"(reload_v)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-02-14 23:48:11 -06:00
|
|
|
int MakeSystemVolume(uint8_t sysPartition);
|
2023-02-17 06:21:43 -06:00
|
|
|
void MakeMBRPartitions();
|
2023-02-14 23:48:11 -06:00
|
|
|
void SystemRun(uint8_t sysPartition) {
|
2023-02-12 00:42:14 -06:00
|
|
|
uint16_t *vga_text = (word *)0xb8000;
|
|
|
|
RestoreVGA();
|
|
|
|
DrawScreen((uint16_t*)0xb8000);
|
|
|
|
|
2023-02-17 01:41:30 -06:00
|
|
|
InitDisk();
|
2024-01-07 22:33:27 -06:00
|
|
|
PITPgrm();
|
2023-02-17 01:41:30 -06:00
|
|
|
|
2023-02-12 00:42:14 -06:00
|
|
|
// Check for FAT partition
|
|
|
|
{
|
2023-02-13 18:23:33 -06:00
|
|
|
while (1) {
|
2023-02-14 23:48:11 -06:00
|
|
|
create_child(GetFreeStack(), (uintptr_t)MakeSystemVolume, 1, sysPartition);
|
2023-02-13 18:23:33 -06:00
|
|
|
if (!check_error_code()) break;
|
2023-02-12 00:42:14 -06:00
|
|
|
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;);
|
|
|
|
}
|
2023-02-17 06:21:43 -06:00
|
|
|
create_child(GetFreeStack(), (uintptr_t)MakeMBRPartitions, 0);
|
2023-02-12 00:42:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2023-02-10 19:20:17 -06:00
|
|
|
uint32_t kernel_check = 0x12345678;
|
2022-09-14 16:50:44 -05:00
|
|
|
void start() {
|
|
|
|
word *vga_text = (word *)0xb8000;
|
|
|
|
char h[] = "LuciaOS";
|
|
|
|
for (int i = 0; i < sizeof(h); i++)
|
|
|
|
*(char *)&vga_text[i] = h[i];
|
2023-02-01 14:18:27 -06:00
|
|
|
vga_text = &vga_text[80];
|
2022-09-14 16:50:44 -05:00
|
|
|
|
2023-02-07 18:52:17 -06:00
|
|
|
// DL *should* be preserved
|
2023-02-13 18:23:33 -06:00
|
|
|
uint16_t boot_dx;
|
|
|
|
asm volatile("nop":"=d"(boot_dx));
|
2023-02-08 11:38:35 -06:00
|
|
|
|
|
|
|
if (!check_cmov()) {
|
|
|
|
char cmov_err[] = "NO CMOV";
|
|
|
|
for (int i = 0; i < sizeof(cmov_err); i++)
|
|
|
|
*(char *)&vga_text[i] = cmov_err[i];
|
|
|
|
for (;;) asm volatile("hlt");
|
|
|
|
}
|
|
|
|
|
2023-02-13 18:23:33 -06:00
|
|
|
vga_text += printWord(boot_dx, vga_text);
|
2023-02-07 18:52:17 -06:00
|
|
|
vga_text++;
|
|
|
|
|
2022-09-14 16:50:44 -05:00
|
|
|
uint32_t o;
|
|
|
|
asm("mov %%esp, %%eax" : "=a"(o) : :);
|
2023-02-01 14:18:27 -06:00
|
|
|
vga_text += printDword(o, vga_text);
|
|
|
|
vga_text++;
|
2022-09-14 16:50:44 -05:00
|
|
|
asm("mov %%ebp, %%eax" : "=a"(o) : :);
|
2023-02-01 14:18:27 -06:00
|
|
|
vga_text += printDword(o, vga_text);
|
|
|
|
vga_text++;
|
2022-09-14 16:50:44 -05:00
|
|
|
|
|
|
|
//char c[] = "APIC support: ";
|
|
|
|
//char apic;
|
|
|
|
//printByte(apic = check_apic(), (short*)&vga_text[80*3 + sizeof(c) - 1]);
|
|
|
|
//for (int i = 0; i < sizeof(c); i++)
|
|
|
|
// *(char *)&vga_text[i+(80*3)] = c[i];
|
|
|
|
//if (!apic) return;
|
|
|
|
|
2023-02-07 18:52:17 -06:00
|
|
|
//char sse_str[] = "SSE support: ";
|
|
|
|
//vga_text += printStr("SSE: ", vga_text);
|
|
|
|
//char sse = check_sse();
|
|
|
|
//if (!sse) {
|
|
|
|
// *vga_text = 'N';
|
|
|
|
//}
|
|
|
|
//vga_text += printStr("Y ", vga_text);
|
|
|
|
//enable_sse();
|
2022-09-14 16:50:44 -05:00
|
|
|
|
2023-01-31 21:26:43 -06:00
|
|
|
//print_flags();
|
2023-02-01 14:18:27 -06:00
|
|
|
vga_text += printStr("CR0:", vga_text);
|
|
|
|
vga_text += printDword(get_cr0(), vga_text);
|
|
|
|
vga_text++;
|
2023-01-31 21:26:43 -06:00
|
|
|
//print_cr3();
|
|
|
|
//print_cr4();
|
2023-02-12 00:42:14 -06:00
|
|
|
|
|
|
|
// Setup system
|
|
|
|
setup_binary();
|
|
|
|
setup_interrupts();
|
|
|
|
setup_tss();
|
|
|
|
init_paging();
|
2023-02-01 20:42:05 -06:00
|
|
|
backup_ivtbios();
|
|
|
|
|
2023-02-13 18:23:33 -06:00
|
|
|
// DL contained disk number, DH contained active partition
|
2023-02-14 23:48:11 -06:00
|
|
|
uint8_t SystemPartition = boot_dx >> 8;
|
2023-02-13 18:23:33 -06:00
|
|
|
|
2023-02-14 23:48:11 -06:00
|
|
|
create_child(GetFreeStack(), (uintptr_t)SystemRun, 1, SystemPartition);
|
2023-02-12 00:42:14 -06:00
|
|
|
// If this returns, something is *very* wrong, reboot the system
|
|
|
|
// TODO Maybe try to recover?
|
|
|
|
|
|
|
|
// Triple fault
|
|
|
|
triple_fault();
|
2022-09-14 16:50:44 -05:00
|
|
|
}
|
|
|
|
|