diff --git a/Applications/Shell/main.cpp b/Applications/Shell/main.cpp index 8ed123ea..dbea2490 100755 --- a/Applications/Shell/main.cpp +++ b/Applications/Shell/main.cpp @@ -1,183 +1,183 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shell.h" - -#define MENU_ITEM_HEIGHT 24 - -fb_info_t videoInfo; -Lemon::GUI::Window* taskbar; -extern Lemon::GUI::Window* menuWindow; -ShellInstance* shell; -surface_t menuButton; - -bool showMenu = true; - -char versionString[80]; - -struct MenuItem{ - char name[64]; - char path[64]; -}; - -MenuItem menuItems[32]; -int menuItemCount = 0; -lemon_sysinfo_t sysInfo; -char memString[128]; - -class WindowButton : public Lemon::GUI::Button { - ShellWindow* win; - -public: - WindowButton(ShellWindow* win, rect_t bounds) : Button(win->title.c_str(), bounds){ - this->win = win; - labelAlignment = Lemon::GUI::TextAlignment::Left; - } - - void Paint(surface_t* surface){ - if(win->state == Lemon::Shell::ShellWindowStateActive || pressed){ - Lemon::Graphics::DrawRect(fixedBounds, {42, 50, 64, 255}, surface); - } - - DrawButtonLabel(surface, false); - } - - void OnMouseUp(vector2i_t mousePos){ - pressed = false; - - if(win->lastState == Lemon::Shell::ShellWindowStateActive){ - window->Minimize(win->id, true); - } else { - window->Minimize(win->id, false); - } - } -}; - -std::map taskbarWindows; -Lemon::GUI::LayoutContainer* taskbarWindowsContainer; - -bool paintTaskbar = true; -void AddWindow(ShellWindow* win){ - WindowButton* btn = new WindowButton(win, {0, 0, 0, 0} /* The LayoutContainer will handle bounds for us*/); - taskbarWindows.insert(std::pair(win, btn)); - - taskbarWindowsContainer->AddWidget(btn); -} - -void RemoveWindow(ShellWindow* win){ - WindowButton* btn = taskbarWindows[win]; - taskbarWindows.erase(win); - - taskbarWindowsContainer->RemoveWidget(btn); - delete btn; -} - -void OnTaskbarPaint(surface_t* surface){ - Lemon::Graphics::DrawGradientVertical(0,0,surface->width, surface->height, {0x33, 0x2c, 0x29, 255}, {0x2e, 0x29, 0x29, 255},surface); - - if(showMenu){ - Lemon::Graphics::surfacecpyTransparent(surface, &menuButton, {18 - menuButton.width / 2, 18 - menuButton.height / 4}, {0, menuButton.height / 2, menuButton.width, 30}); - } else { - Lemon::Graphics::surfacecpyTransparent(surface, &menuButton, {18 - menuButton.width / 2, 18 - menuButton.height / 4}, {0, 0, menuButton.width, 30}); - } - - sprintf(memString, "Used Memory: %lu/%lu KB", sysInfo.usedMem, sysInfo.totalMem); - Lemon::Graphics::DrawString(memString, surface->width - Lemon::Graphics::GetTextLength(memString) - 8, 10, 255, 255, 255, surface); -} - -void InitializeMenu(); -void PollMenu(); -void MinimizeMenu(bool s); - -int main(){ - handle_t svc = Lemon::CreateService("lemon.shell"); - shell = new ShellInstance(svc, "Instance"); - - syscall(SYS_GET_VIDEO_MODE, (uintptr_t)&videoInfo,0,0,0,0); - syscall(SYS_UNAME, (uintptr_t)versionString,0,0,0,0); - - Lemon::Graphics::LoadImage("/initrd/menubuttons.png", &menuButton); - - handle_t tempEndpoint = 0; - while(tempEndpoint <= 0){ - tempEndpoint = Lemon::InterfaceConnect("lemon.lemonwm/Instance"); - } // Wait for LemonWM to create the interface (if not already created) - Lemon::DestroyKObject(tempEndpoint); - - taskbar = new Lemon::GUI::Window("", {static_cast(videoInfo.width), 36}, WINDOW_FLAGS_NODECORATION | WINDOW_FLAGS_NOSHELL, Lemon::GUI::WindowType::GUI, {0, static_cast(videoInfo.height) - 36}); - taskbar->OnPaint = OnTaskbarPaint; - taskbar->rootContainer.background = {0, 0, 0, 0}; - taskbarWindowsContainer = new Lemon::GUI::LayoutContainer({40, 0, static_cast(videoInfo.width) - 104, static_cast(videoInfo.height)}, {160, 36 - 4}); - taskbarWindowsContainer->background = {0, 0, 0, 0}; - taskbar->AddWidget(taskbarWindowsContainer); - - shell->AddWindow = AddWindow; - shell->RemoveWindow = RemoveWindow; - - InitializeMenu(); - - taskbar->InitializeShellConnection(); - - Lemon::Waiter waiter; - waiter.WaitOnAll(&shell->GetInterface()); - waiter.WaitOn(taskbar); - waiter.WaitOn(menuWindow); - - for(;;){ - shell->Update(); - - Lemon::LemonEvent ev; - while(taskbar->PollEvent(ev)){ - if(ev.event == Lemon::EventMouseReleased){ - if(ev.mousePos.x < 100){ - showMenu = !showMenu; - - MinimizeMenu(!showMenu); - } else { - taskbar->GUIHandleEvent(ev); - } - } else { - taskbar->GUIHandleEvent(ev); - } - paintTaskbar = true; - } - - PollMenu(); - - uint64_t usedMemLast = sysInfo.usedMem; - sysInfo = Lemon::SysInfo(); - - if(sysInfo.usedMem != usedMemLast) paintTaskbar = true; - - if(paintTaskbar){ - taskbar->Paint(); - - paintTaskbar = false; - } - - waiter.Wait(); - } - - for(;;); -} +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shell.h" + +#define MENU_ITEM_HEIGHT 24 + +fb_info_t videoInfo; +Lemon::GUI::Window* taskbar; +extern Lemon::GUI::Window* menuWindow; +ShellInstance* shell; +surface_t menuButton; + +bool showMenu = true; + +char versionString[80]; + +struct MenuItem{ + char name[64]; + char path[64]; +}; + +MenuItem menuItems[32]; +int menuItemCount = 0; +lemon_sysinfo_t sysInfo; +char memString[128]; + +class WindowButton : public Lemon::GUI::Button { + ShellWindow* win; + +public: + WindowButton(ShellWindow* win, rect_t bounds) : Button(win->title.c_str(), bounds){ + this->win = win; + labelAlignment = Lemon::GUI::TextAlignment::Left; + } + + void Paint(surface_t* surface){ + if(win->state == Lemon::Shell::ShellWindowStateActive || pressed){ + Lemon::Graphics::DrawRect(fixedBounds, {42, 50, 64, 255}, surface); + } + + DrawButtonLabel(surface, false); + } + + void OnMouseUp(vector2i_t mousePos){ + pressed = false; + + if(win->lastState == Lemon::Shell::ShellWindowStateActive){ + window->Minimize(win->id, true); + } else { + window->Minimize(win->id, false); + } + } +}; + +std::map taskbarWindows; +Lemon::GUI::LayoutContainer* taskbarWindowsContainer; + +bool paintTaskbar = true; +void AddWindow(ShellWindow* win){ + WindowButton* btn = new WindowButton(win, {0, 0, 0, 0} /* The LayoutContainer will handle bounds for us*/); + taskbarWindows.insert(std::pair(win, btn)); + + taskbarWindowsContainer->AddWidget(btn); +} + +void RemoveWindow(ShellWindow* win){ + WindowButton* btn = taskbarWindows[win]; + taskbarWindows.erase(win); + + taskbarWindowsContainer->RemoveWidget(btn); + delete btn; +} + +void OnTaskbarPaint(surface_t* surface){ + Lemon::Graphics::DrawGradientVertical(0,0,surface->width, surface->height, {0x33, 0x2c, 0x29, 255}, {0x2e, 0x29, 0x29, 255},surface); + + if(showMenu){ + Lemon::Graphics::surfacecpyTransparent(surface, &menuButton, {18 - menuButton.width / 2, 18 - menuButton.height / 4}, {0, menuButton.height / 2, menuButton.width, 30}); + } else { + Lemon::Graphics::surfacecpyTransparent(surface, &menuButton, {18 - menuButton.width / 2, 18 - menuButton.height / 4}, {0, 0, menuButton.width, 30}); + } + + sprintf(memString, "Used Memory: %lu/%lu KB", sysInfo.usedMem, sysInfo.totalMem); + Lemon::Graphics::DrawString(memString, surface->width - Lemon::Graphics::GetTextLength(memString) - 8, 10, 255, 255, 255, surface); +} + +void InitializeMenu(); +void PollMenu(); +void MinimizeMenu(bool s); + +int main(){ + handle_t svc = Lemon::CreateService("lemon.shell"); + shell = new ShellInstance(svc, "Instance"); + + syscall(SYS_GET_VIDEO_MODE, (uintptr_t)&videoInfo,0,0,0,0); + syscall(SYS_UNAME, (uintptr_t)versionString,0,0,0,0); + + Lemon::Graphics::LoadImage("/initrd/menubuttons.png", &menuButton); + + handle_t tempEndpoint = 0; + while(tempEndpoint <= 0){ + tempEndpoint = Lemon::InterfaceConnect("lemon.lemonwm/Instance"); + } // Wait for LemonWM to create the interface (if not already created) + Lemon::DestroyKObject(tempEndpoint); + + taskbar = new Lemon::GUI::Window("", {static_cast(videoInfo.width), 36}, WINDOW_FLAGS_NODECORATION | WINDOW_FLAGS_NOSHELL, Lemon::GUI::WindowType::GUI, {0, static_cast(videoInfo.height) - 36}); + taskbar->OnPaint = OnTaskbarPaint; + taskbar->rootContainer.background = {0, 0, 0, 0}; + taskbarWindowsContainer = new Lemon::GUI::LayoutContainer({40, 0, static_cast(videoInfo.width) - 104, static_cast(videoInfo.height)}, {160, 36 - 4}); + taskbarWindowsContainer->background = {0, 0, 0, 0}; + taskbar->AddWidget(taskbarWindowsContainer); + + shell->AddWindow = AddWindow; + shell->RemoveWindow = RemoveWindow; + + InitializeMenu(); + + taskbar->InitializeShellConnection(); + + Lemon::Waiter waiter; + waiter.WaitOnAll(&shell->GetInterface()); + waiter.WaitOn(taskbar); + waiter.WaitOn(menuWindow); + + for(;;){ + shell->Update(); + + Lemon::LemonEvent ev; + while(taskbar->PollEvent(ev)){ + if(ev.event == Lemon::EventMouseReleased){ + if(ev.mousePos.x < 100){ + showMenu = !showMenu; + + MinimizeMenu(!showMenu); + } else { + taskbar->GUIHandleEvent(ev); + } + } else { + taskbar->GUIHandleEvent(ev); + } + paintTaskbar = true; + } + + PollMenu(); + + uint64_t usedMemLast = sysInfo.usedMem; + sysInfo = Lemon::SysInfo(); + + if(sysInfo.usedMem != usedMemLast) paintTaskbar = true; + + if(paintTaskbar){ + taskbar->Paint(); + + paintTaskbar = false; + } + + waiter.Wait(); + } + + for(;;); +} diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp index 07b1ebfa..4218b860 100755 --- a/Applications/Terminal/main.cpp +++ b/Applications/Terminal/main.cpp @@ -1,600 +1,600 @@ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "escape.h" -#include "colours.h" - -#define TASKBAR_COLOUR_R 128 -#define TASKBAR_COLOUR_G 128 -#define TASKBAR_COLOUR_B 128 - -#define MENU_WIDTH 200 -#define MENU_HEIGHT 300 - -Lemon::GUI::Window* window; - -bool paintAll = true; - -struct TermState{ - bool bold : 1; - bool italic : 1; - bool faint : 1; - bool underline : 1; - bool blink : 1; - bool reverse : 1; - bool strikethrough: 1; - - uint8_t fgColour; - uint8_t bgColour; -}; - -TermState defaultState { - .bold = 0, - .italic = 0, - .faint = 0, - .underline = 0, - .blink = 0, - .reverse = 0, - .strikethrough = 0, - .fgColour = 7, - .bgColour = 0, -}; - -struct TerminalChar { - TermState s; - char c; -}; - -Lemon::Graphics::Font* terminalFont; - -TermState state = defaultState; - -bool escapeSequence = false; -int escapeType = 0; - -surface_t menuSurface; -surface_t windowSurface; - -int bufferOffset = 0; -int columnCount = 80; -int rowCount = 25; -std::vector> buffer; - -vector2i_t curPos = {0, 0}; -vector2i_t storedCurPos = {0, 0}; - -const int escBufMax = 256; - -char escBuf[escBufMax]; - -char charactersPerLine; - -void Scroll(){ - if(curPos.y >= rowCount){ - bufferOffset += curPos.y - (rowCount - 1); - curPos.y = rowCount - 1; - } - - while(static_cast(bufferOffset + rowCount) >= buffer.size()) buffer.push_back(std::vector()); - - if(buffer.size() > 2000){ - buffer.erase(buffer.begin() + 2000, buffer.end()); - } - - paintAll = true; -} - -void OnPaint(surface_t* surface){ - int fontHeight = terminalFont->lineHeight; - - if(true){ - for(int i = 0; i < rowCount && (bufferOffset + i) < static_cast(buffer.size()); i++){ - int j = 0; - for(; j < static_cast(buffer[bufferOffset + i].size()); j++){ - TerminalChar ch = buffer[bufferOffset + i][j]; - rgba_colour_t fg = colours[ch.s.fgColour]; - rgba_colour_t bg = colours[ch.s.bgColour]; - Lemon::Graphics::DrawRect(j * 8, i * fontHeight, 8, fontHeight, bg.r, bg.g, bg.b, surface); - Lemon::Graphics::DrawChar(ch.c, j * 8, i * fontHeight, fg.r, fg.g, fg.b, surface, terminalFont); - } - - Lemon::Graphics::DrawRect(j * 8, i * fontHeight, window->GetSize().x - j * 8, fontHeight, colours[state.bgColour], surface); - } - } else { - int j = 0; - for(; j < static_cast(buffer[bufferOffset + curPos.y].size()); j++){ - TerminalChar ch = buffer[bufferOffset + curPos.y][j]; - rgba_colour_t fg = colours[ch.s.fgColour]; - rgba_colour_t bg = colours[ch.s.bgColour]; - Lemon::Graphics::DrawRect(j * 8, curPos.y * fontHeight, 8, fontHeight, bg.r, bg.g, bg.b, surface); - Lemon::Graphics::DrawChar(ch.c, j * 8, curPos.y * fontHeight, fg.r, fg.g, fg.b, surface, terminalFont); - } - - Lemon::Graphics::DrawRect(j * 8, curPos.y * fontHeight, window->GetSize().x - j * 8, fontHeight, colours[state.bgColour], surface); - } - - Lemon::Graphics::DrawRect(curPos.x * 8, curPos.y * fontHeight + (fontHeight / 4 * 3), 8, fontHeight / 4, colours[0x7] /* Grey */, surface); - - paintAll = false; -} - -void DoAnsiSGR(){ - int r = -1; - if(strchr(escBuf, ';')){ - char temp[strchr(escBuf, ';') - escBuf + 1]; - temp[strchr(escBuf, ';') - escBuf] = 0; - strncpy(temp, escBuf, (int)(strchr(escBuf, ';') - escBuf)); - r = atoi(escBuf); - - } else r = atoi(escBuf); - if(r < 30){ - switch (r) - { - case 0: - state = defaultState; - break; - case 1: - state.bold = true; - break; - case 2: - state.faint = true; - break; - case 3: - state.italic = true; - break; - case 4: - state.underline = true; - break; - case 5: - case 6: - state.blink = true; - break; - case 7: - state.reverse = true; - break; - case 9: - state.strikethrough = true; - break; - case 21: - state.underline = true; - break; - case 24: - state.underline = false; - break; - case 25: - state.blink = false; - break; - case 27: - state.reverse = false; - break; - default: - break; - } - } else if (r >= ANSI_CSI_SGR_FG_BLACK && r <= ANSI_CSI_SGR_FG_WHITE){ // Foreground Colour - state.fgColour = r - ANSI_CSI_SGR_FG_BLACK; - } else if (r >= ANSI_CSI_SGR_BG_BLACK && r <= ANSI_CSI_SGR_BG_WHITE){ // Background Colour - state.bgColour = r - ANSI_CSI_SGR_BG_BLACK; - } else if (r >= ANSI_CSI_SGR_FG_BLACK_BRIGHT && r <= ANSI_CSI_SGR_FG_WHITE_BRIGHT){ // Foreground Colour (Bright) - state.fgColour = r - ANSI_CSI_SGR_FG_BLACK_BRIGHT + 8; - } else if (r >= ANSI_CSI_SGR_BG_BLACK_BRIGHT && r <= ANSI_CSI_SGR_BG_WHITE_BRIGHT){ // Background Colour (Bright) - state.bgColour = r - ANSI_CSI_SGR_BG_BLACK_BRIGHT + 8; - } else if (r == ANSI_CSI_SGR_FG){ - if(strchr(escBuf, ';') && *(strchr(escBuf, ';') + 1) == '5' && strchr(strchr(escBuf, ';') + 1, ';')/* Check if 2 arguments are given */){ // Next argument should be '5' for 256 colours - state.fgColour = atoi(strchr(strchr(escBuf, ';') + 1, ';') + 1); // Get argument - } - } else if (r == ANSI_CSI_SGR_BG){ - if(strchr(escBuf, ';') && *(strchr(escBuf, ';') + 1) == '5' && strchr(strchr(escBuf, ';') + 1, ';')/* Check if 2 arguments are given */){ // Next argument should be '5' for 256 colours - state.bgColour = atoi(strchr(strchr(escBuf, ';') + 1, ';') + 1); // Get argument - } - } -} - -void DoAnsiCSI(char ch){ - switch(ch){ - case ANSI_CSI_SGR: - DoAnsiSGR(); // Set Graphics Rendition - break; - case ANSI_CSI_CUU: - { - int amount = 1; - if(strlen(escBuf)){ - amount = atoi(escBuf); - } - - paintAll = true; - - curPos.y -= amount; - if(curPos.y < 0) curPos.y = 0; - break; - } - case ANSI_CSI_CUD: - { - int amount = 1; - if(strlen(escBuf)){ - amount = atoi(escBuf); - } - - curPos.y += amount; - Scroll(); - break; - } - case ANSI_CSI_CUF: - { - int amount = 1; - if(strlen(escBuf)){ - amount = atoi(escBuf); - } - curPos.x += amount; - if(curPos.x > columnCount) { - curPos.x = 0; - curPos.y++; - Scroll(); - } - break; - } - case ANSI_CSI_CUB: - { - int amount = 1; - if(strlen(escBuf)){ - amount = atoi(escBuf); - } - curPos.x -= amount; - if(curPos.x < 0) { - curPos.x = columnCount - 1; - curPos.y--; - - paintAll = true; - } - if(curPos.y < 0) curPos.y = 0; - break; - } - case ANSI_CSI_CUP: // Set cursor position - { - char* scolon = strchr(escBuf, ';'); - if(scolon){ - *scolon = 0; - - curPos.y = atoi(escBuf) - 1; - Scroll(); - - if(*(scolon + 1) == 0){ - curPos.x = 0; - } else { - curPos.x = atoi(scolon + 1) - 1; - } - } else { - curPos.x = 0; - curPos.y = 0; - } - - paintAll = true; - } - break; - case ANSI_CSI_ED: - { - int num = atoi(escBuf); - switch(num){ - case 0: // Clear entire screen from cursor - for(int i = curPos.y + 1; i < rowCount && i + bufferOffset < static_cast(buffer.size()); i++){ - buffer[bufferOffset + i].clear(); - } - paintAll = true; - break; - case 1: // Clear screen and move cursor - case 2: // Same as 1 but delete everything in the scrollback buffer - buffer.clear(); - curPos = {0, 0}; - bufferOffset = 0; - for(int i = 0; i < rowCount; i++){ - buffer.push_back(std::vector()); - } - paintAll = true; - break; - } - } - break; - case ANSI_CSI_EL: - { - int n = 0; - if(strlen(escBuf)){ - n = atoi(escBuf); - } - - switch (n) - { - case 2: // Clear entire screen - curPos.y = 0; - curPos.x = 0; - - buffer.erase(buffer.begin() + bufferOffset); - paintAll = true; - break; - case 1: // Clear from cursor to beginning of line - buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin(), buffer[bufferOffset + curPos.y].begin() + curPos.x); - break; - case 0: // Clear from cursor to end of line - default: - buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin() + curPos.x, buffer[bufferOffset + curPos.y].end()); - break; - } - break; - } - case ANSI_CSI_IL: // Insert blank lines - { - int amount = atoi(escBuf); - buffer.insert(buffer.begin() + bufferOffset + curPos.y, amount, std::vector()); - - paintAll = true; - break; - } - case ANSI_CSI_DL: - { - int amount = atoi(escBuf); - buffer.erase(buffer.begin() + bufferOffset + curPos.y - amount, buffer.begin() + bufferOffset + curPos.y); - - while(static_cast(buffer.size()) - bufferOffset < rowCount){ - buffer.push_back(std::vector()); - } - - paintAll = true; - break; - } - case ANSI_CSI_SU: // Scroll Up - if(strlen(escBuf)){ - bufferOffset += atoi(escBuf); - } else { - bufferOffset++; - } - - while(static_cast(buffer.size()) - bufferOffset < rowCount){ - buffer.push_back(std::vector()); - } - - paintAll = true; - break; - case ANSI_CSI_SD: // Scroll Down - if(strlen(escBuf)){ - buffer.insert(buffer.begin() + bufferOffset, atoi(escBuf), std::vector()); - //bufferOffset -= atoi(escBuf); - - paintAll = true; - } else { - buffer.insert(buffer.begin() + bufferOffset, 1, std::vector()); - //bufferOffset--; - - paintAll = true; - } - break; - default: - //fprintf(stderr, "Unknown Control Sequence Introducer (CSI) '%c'\n", ch); - break; - } -} - -void DoAnsiOSC(char ch){ - -} - -void PrintChar(char ch){ - if(escapeSequence){ - if(isspace(ch)){ - return; - } - - if(!escapeType){ - escapeType = ch; - ch = 0; - } - - if(escapeType == ANSI_CSI || escapeType == ANSI_OSC){ - if(!isalpha(ch)){ // Found output sequence - if(strlen(escBuf) >= escBufMax){ - escapeSequence = false; - return; - } - char s[] = {ch, 0}; - strncat(escBuf, s, 2); // Add to buff - return; - } - - if(escapeType == ANSI_CSI){ - DoAnsiCSI(ch); - } else if (escapeType == ANSI_OSC) { - DoAnsiOSC(ch); - } - } else if (escapeType == ANSI_RIS){ - state = defaultState; - buffer.clear(); - curPos = {0, 0}; - bufferOffset = 0; - for(int i = 0; i < rowCount; i++){ - buffer.push_back(std::vector()); - } - } else if(escapeType == ESC_SAVE_CURSOR) { - storedCurPos = curPos; - } else if(escapeType == ESC_RESTORE_CURSOR) { - curPos = storedCurPos; - } else { - //fprintf(stderr, "Unknown ANSI escape code '%c'\n", ch); - } - escapeSequence = 0; - escapeType = 0; - } else { - - switch (ch) - { - case ANSI_ESC: - escapeSequence = true; - escapeType = 0; - escBuf[0] = 0; - break; - case '\r': - curPos.x = 0; - break; - case '\n': - curPos.y++; - curPos.x = 0; - Scroll(); - break; - case '\b': - if(curPos.x > 0) curPos.x--; - else if(curPos.y > 0) { - curPos.y--; - curPos.x = buffer[bufferOffset + curPos.y].size(); - - paintAll = true; - } - - buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin() + curPos.x); - break; - case ' ': - default: - if(!(isgraph(ch) || isspace(ch))) break; - - if(curPos.x > columnCount){ - curPos.y++; - curPos.x = 0; - Scroll(); - } - - if(static_cast(curPos.x) >= buffer[bufferOffset + curPos.y].size()) - buffer[bufferOffset + curPos.y].push_back({.s = state, .c = ch}); - else - buffer[bufferOffset + curPos.y][curPos.x] = {.s = state, .c = ch}; - - curPos.x++; - - if(curPos.x > columnCount){ - curPos.x = 0; - curPos.y++; - Scroll(); - } - - break; - } - } -} - -extern "C" -int main(int argc, char** argv){ - terminalFont = Lemon::Graphics::LoadFont("/initrd/sourcecodepro.ttf", "termmonospace"); - if(!terminalFont){ - terminalFont = Lemon::Graphics::GetFont("default"); - } - - window = new Lemon::GUI::Window("Terminal", {720, 32 * terminalFont->lineHeight}); - - rowCount = window->GetSize().y / terminalFont->lineHeight; - columnCount = 720 / 8; - - curPos = {0, 0}; - - for(int i = 0; i < rowCount; i++){ - buffer.push_back(std::vector()); - } - - - int masterPTYFd; - syscall(SYS_GRANT_PTY, (uintptr_t)&masterPTYFd, 0, 0, 0, 0); - - setenv("TERM", "xterm-256color", 1); // the Lemon OS terminal is (fairly) xterm compatible (256 colour, etc.) - - char* const _argv[] = {const_cast("/system/bin/lsh.lef")}; - lemon_spawn(_argv[0], 1, _argv, 1); - - window->OnPaint = OnPaint; - - char* _buf = (char*)malloc(512); - - winsize wSz = { - .ws_row = static_cast(rowCount), - .ws_col = static_cast(columnCount), - .ws_xpixel = static_cast(window->GetSize().x), - .ws_ypixel = static_cast(window->GetSize().y), - }; - - ioctl(masterPTYFd, TIOCSWINSZ, &wSz); - - std::vector fds; - fds.push_back({.fd = masterPTYFd, .events = POLLIN, .revents = 0}); - - //auto& wMHandler = window->GetHandler(); - //fds.insert(fds.begin(), wMHandler.GetFileDescriptors().begin(), wMHandler.GetFileDescriptors().end()); - for(;;){ - Lemon::LemonEvent ev; - while(window->PollEvent(ev)){ - if(ev.event == Lemon::EventKeyPressed){ - if(ev.key == KEY_ARROW_UP){ - const char* esc = "\e[A"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_ARROW_DOWN){ - const char* esc = "\e[B"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_ARROW_RIGHT){ - const char* esc = "\e[C"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_ARROW_LEFT){ - const char* esc = "\e[D"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_END){ - const char* esc = "\e[F"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_HOME){ - const char* esc = "\e[H"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key == KEY_ESCAPE){ - const char* esc = "\e\e"; - write(masterPTYFd, esc, strlen(esc)); - } else if(ev.key < 128){ - const char key = (char)ev.key; - write(masterPTYFd, &key, 1); - } - } else if (ev.event == Lemon::EventWindowClosed){ - delete window; - exit(0); - return 0; - } else if (ev.event == Lemon::EventWindowResize){ - window->Resize(ev.resizeBounds); - - columnCount = window->GetSize().x / 8; - rowCount = window->GetSize().y / terminalFont->lineHeight; - - wSz.ws_col = static_cast(columnCount); - wSz.ws_row = static_cast(rowCount); - wSz.ws_xpixel = static_cast(window->GetSize().x); - wSz.ws_ypixel = static_cast(window->GetSize().y); - - ioctl(masterPTYFd, TIOCSWINSZ, &wSz); - paintAll = true; - } - } - - while(int len = read(masterPTYFd, _buf, 512)){ - for(int i = 0; i < len; i++){ - PrintChar(_buf[i]); - } - } - - window->Paint(); - - //poll(fds.data(), fds.size(), -1); - } - return 0; -} +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "escape.h" +#include "colours.h" + +#define TASKBAR_COLOUR_R 128 +#define TASKBAR_COLOUR_G 128 +#define TASKBAR_COLOUR_B 128 + +#define MENU_WIDTH 200 +#define MENU_HEIGHT 300 + +Lemon::GUI::Window* window; + +bool paintAll = true; + +struct TermState{ + bool bold : 1; + bool italic : 1; + bool faint : 1; + bool underline : 1; + bool blink : 1; + bool reverse : 1; + bool strikethrough: 1; + + uint8_t fgColour; + uint8_t bgColour; +}; + +TermState defaultState { + .bold = 0, + .italic = 0, + .faint = 0, + .underline = 0, + .blink = 0, + .reverse = 0, + .strikethrough = 0, + .fgColour = 7, + .bgColour = 0, +}; + +struct TerminalChar { + TermState s; + char c; +}; + +Lemon::Graphics::Font* terminalFont; + +TermState state = defaultState; + +bool escapeSequence = false; +int escapeType = 0; + +surface_t menuSurface; +surface_t windowSurface; + +int bufferOffset = 0; +int columnCount = 80; +int rowCount = 25; +std::vector> buffer; + +vector2i_t curPos = {0, 0}; +vector2i_t storedCurPos = {0, 0}; + +const int escBufMax = 256; + +char escBuf[escBufMax]; + +char charactersPerLine; + +void Scroll(){ + if(curPos.y >= rowCount){ + bufferOffset += curPos.y - (rowCount - 1); + curPos.y = rowCount - 1; + } + + while(static_cast(bufferOffset + rowCount) >= buffer.size()) buffer.push_back(std::vector()); + + if(buffer.size() > 2000){ + buffer.erase(buffer.begin() + 2000, buffer.end()); + } + + paintAll = true; +} + +void OnPaint(surface_t* surface){ + int fontHeight = terminalFont->lineHeight; + + if(true){ + for(int i = 0; i < rowCount && (bufferOffset + i) < static_cast(buffer.size()); i++){ + int j = 0; + for(; j < static_cast(buffer[bufferOffset + i].size()); j++){ + TerminalChar ch = buffer[bufferOffset + i][j]; + rgba_colour_t fg = colours[ch.s.fgColour]; + rgba_colour_t bg = colours[ch.s.bgColour]; + Lemon::Graphics::DrawRect(j * 8, i * fontHeight, 8, fontHeight, bg.r, bg.g, bg.b, surface); + Lemon::Graphics::DrawChar(ch.c, j * 8, i * fontHeight, fg.r, fg.g, fg.b, surface, terminalFont); + } + + Lemon::Graphics::DrawRect(j * 8, i * fontHeight, window->GetSize().x - j * 8, fontHeight, colours[state.bgColour], surface); + } + } else { + int j = 0; + for(; j < static_cast(buffer[bufferOffset + curPos.y].size()); j++){ + TerminalChar ch = buffer[bufferOffset + curPos.y][j]; + rgba_colour_t fg = colours[ch.s.fgColour]; + rgba_colour_t bg = colours[ch.s.bgColour]; + Lemon::Graphics::DrawRect(j * 8, curPos.y * fontHeight, 8, fontHeight, bg.r, bg.g, bg.b, surface); + Lemon::Graphics::DrawChar(ch.c, j * 8, curPos.y * fontHeight, fg.r, fg.g, fg.b, surface, terminalFont); + } + + Lemon::Graphics::DrawRect(j * 8, curPos.y * fontHeight, window->GetSize().x - j * 8, fontHeight, colours[state.bgColour], surface); + } + + Lemon::Graphics::DrawRect(curPos.x * 8, curPos.y * fontHeight + (fontHeight / 4 * 3), 8, fontHeight / 4, colours[0x7] /* Grey */, surface); + + paintAll = false; +} + +void DoAnsiSGR(){ + int r = -1; + if(strchr(escBuf, ';')){ + char temp[strchr(escBuf, ';') - escBuf + 1]; + temp[strchr(escBuf, ';') - escBuf] = 0; + strncpy(temp, escBuf, (int)(strchr(escBuf, ';') - escBuf)); + r = atoi(escBuf); + + } else r = atoi(escBuf); + if(r < 30){ + switch (r) + { + case 0: + state = defaultState; + break; + case 1: + state.bold = true; + break; + case 2: + state.faint = true; + break; + case 3: + state.italic = true; + break; + case 4: + state.underline = true; + break; + case 5: + case 6: + state.blink = true; + break; + case 7: + state.reverse = true; + break; + case 9: + state.strikethrough = true; + break; + case 21: + state.underline = true; + break; + case 24: + state.underline = false; + break; + case 25: + state.blink = false; + break; + case 27: + state.reverse = false; + break; + default: + break; + } + } else if (r >= ANSI_CSI_SGR_FG_BLACK && r <= ANSI_CSI_SGR_FG_WHITE){ // Foreground Colour + state.fgColour = r - ANSI_CSI_SGR_FG_BLACK; + } else if (r >= ANSI_CSI_SGR_BG_BLACK && r <= ANSI_CSI_SGR_BG_WHITE){ // Background Colour + state.bgColour = r - ANSI_CSI_SGR_BG_BLACK; + } else if (r >= ANSI_CSI_SGR_FG_BLACK_BRIGHT && r <= ANSI_CSI_SGR_FG_WHITE_BRIGHT){ // Foreground Colour (Bright) + state.fgColour = r - ANSI_CSI_SGR_FG_BLACK_BRIGHT + 8; + } else if (r >= ANSI_CSI_SGR_BG_BLACK_BRIGHT && r <= ANSI_CSI_SGR_BG_WHITE_BRIGHT){ // Background Colour (Bright) + state.bgColour = r - ANSI_CSI_SGR_BG_BLACK_BRIGHT + 8; + } else if (r == ANSI_CSI_SGR_FG){ + if(strchr(escBuf, ';') && *(strchr(escBuf, ';') + 1) == '5' && strchr(strchr(escBuf, ';') + 1, ';')/* Check if 2 arguments are given */){ // Next argument should be '5' for 256 colours + state.fgColour = atoi(strchr(strchr(escBuf, ';') + 1, ';') + 1); // Get argument + } + } else if (r == ANSI_CSI_SGR_BG){ + if(strchr(escBuf, ';') && *(strchr(escBuf, ';') + 1) == '5' && strchr(strchr(escBuf, ';') + 1, ';')/* Check if 2 arguments are given */){ // Next argument should be '5' for 256 colours + state.bgColour = atoi(strchr(strchr(escBuf, ';') + 1, ';') + 1); // Get argument + } + } +} + +void DoAnsiCSI(char ch){ + switch(ch){ + case ANSI_CSI_SGR: + DoAnsiSGR(); // Set Graphics Rendition + break; + case ANSI_CSI_CUU: + { + int amount = 1; + if(strlen(escBuf)){ + amount = atoi(escBuf); + } + + paintAll = true; + + curPos.y -= amount; + if(curPos.y < 0) curPos.y = 0; + break; + } + case ANSI_CSI_CUD: + { + int amount = 1; + if(strlen(escBuf)){ + amount = atoi(escBuf); + } + + curPos.y += amount; + Scroll(); + break; + } + case ANSI_CSI_CUF: + { + int amount = 1; + if(strlen(escBuf)){ + amount = atoi(escBuf); + } + curPos.x += amount; + if(curPos.x > columnCount) { + curPos.x = 0; + curPos.y++; + Scroll(); + } + break; + } + case ANSI_CSI_CUB: + { + int amount = 1; + if(strlen(escBuf)){ + amount = atoi(escBuf); + } + curPos.x -= amount; + if(curPos.x < 0) { + curPos.x = columnCount - 1; + curPos.y--; + + paintAll = true; + } + if(curPos.y < 0) curPos.y = 0; + break; + } + case ANSI_CSI_CUP: // Set cursor position + { + char* scolon = strchr(escBuf, ';'); + if(scolon){ + *scolon = 0; + + curPos.y = atoi(escBuf) - 1; + Scroll(); + + if(*(scolon + 1) == 0){ + curPos.x = 0; + } else { + curPos.x = atoi(scolon + 1) - 1; + } + } else { + curPos.x = 0; + curPos.y = 0; + } + + paintAll = true; + } + break; + case ANSI_CSI_ED: + { + int num = atoi(escBuf); + switch(num){ + case 0: // Clear entire screen from cursor + for(int i = curPos.y + 1; i < rowCount && i + bufferOffset < static_cast(buffer.size()); i++){ + buffer[bufferOffset + i].clear(); + } + paintAll = true; + break; + case 1: // Clear screen and move cursor + case 2: // Same as 1 but delete everything in the scrollback buffer + buffer.clear(); + curPos = {0, 0}; + bufferOffset = 0; + for(int i = 0; i < rowCount; i++){ + buffer.push_back(std::vector()); + } + paintAll = true; + break; + } + } + break; + case ANSI_CSI_EL: + { + int n = 0; + if(strlen(escBuf)){ + n = atoi(escBuf); + } + + switch (n) + { + case 2: // Clear entire screen + curPos.y = 0; + curPos.x = 0; + + buffer.erase(buffer.begin() + bufferOffset); + paintAll = true; + break; + case 1: // Clear from cursor to beginning of line + buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin(), buffer[bufferOffset + curPos.y].begin() + curPos.x); + break; + case 0: // Clear from cursor to end of line + default: + buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin() + curPos.x, buffer[bufferOffset + curPos.y].end()); + break; + } + break; + } + case ANSI_CSI_IL: // Insert blank lines + { + int amount = atoi(escBuf); + buffer.insert(buffer.begin() + bufferOffset + curPos.y, amount, std::vector()); + + paintAll = true; + break; + } + case ANSI_CSI_DL: + { + int amount = atoi(escBuf); + buffer.erase(buffer.begin() + bufferOffset + curPos.y - amount, buffer.begin() + bufferOffset + curPos.y); + + while(static_cast(buffer.size()) - bufferOffset < rowCount){ + buffer.push_back(std::vector()); + } + + paintAll = true; + break; + } + case ANSI_CSI_SU: // Scroll Up + if(strlen(escBuf)){ + bufferOffset += atoi(escBuf); + } else { + bufferOffset++; + } + + while(static_cast(buffer.size()) - bufferOffset < rowCount){ + buffer.push_back(std::vector()); + } + + paintAll = true; + break; + case ANSI_CSI_SD: // Scroll Down + if(strlen(escBuf)){ + buffer.insert(buffer.begin() + bufferOffset, atoi(escBuf), std::vector()); + //bufferOffset -= atoi(escBuf); + + paintAll = true; + } else { + buffer.insert(buffer.begin() + bufferOffset, 1, std::vector()); + //bufferOffset--; + + paintAll = true; + } + break; + default: + //fprintf(stderr, "Unknown Control Sequence Introducer (CSI) '%c'\n", ch); + break; + } +} + +void DoAnsiOSC(char ch){ + +} + +void PrintChar(char ch){ + if(escapeSequence){ + if(isspace(ch)){ + return; + } + + if(!escapeType){ + escapeType = ch; + ch = 0; + } + + if(escapeType == ANSI_CSI || escapeType == ANSI_OSC){ + if(!isalpha(ch)){ // Found output sequence + if(strlen(escBuf) >= escBufMax){ + escapeSequence = false; + return; + } + char s[] = {ch, 0}; + strncat(escBuf, s, 2); // Add to buff + return; + } + + if(escapeType == ANSI_CSI){ + DoAnsiCSI(ch); + } else if (escapeType == ANSI_OSC) { + DoAnsiOSC(ch); + } + } else if (escapeType == ANSI_RIS){ + state = defaultState; + buffer.clear(); + curPos = {0, 0}; + bufferOffset = 0; + for(int i = 0; i < rowCount; i++){ + buffer.push_back(std::vector()); + } + } else if(escapeType == ESC_SAVE_CURSOR) { + storedCurPos = curPos; + } else if(escapeType == ESC_RESTORE_CURSOR) { + curPos = storedCurPos; + } else { + //fprintf(stderr, "Unknown ANSI escape code '%c'\n", ch); + } + escapeSequence = 0; + escapeType = 0; + } else { + + switch (ch) + { + case ANSI_ESC: + escapeSequence = true; + escapeType = 0; + escBuf[0] = 0; + break; + case '\r': + curPos.x = 0; + break; + case '\n': + curPos.y++; + curPos.x = 0; + Scroll(); + break; + case '\b': + if(curPos.x > 0) curPos.x--; + else if(curPos.y > 0) { + curPos.y--; + curPos.x = buffer[bufferOffset + curPos.y].size(); + + paintAll = true; + } + + buffer[bufferOffset + curPos.y].erase(buffer[bufferOffset + curPos.y].begin() + curPos.x); + break; + case ' ': + default: + if(!(isgraph(ch) || isspace(ch))) break; + + if(curPos.x > columnCount){ + curPos.y++; + curPos.x = 0; + Scroll(); + } + + if(static_cast(curPos.x) >= buffer[bufferOffset + curPos.y].size()) + buffer[bufferOffset + curPos.y].push_back({.s = state, .c = ch}); + else + buffer[bufferOffset + curPos.y][curPos.x] = {.s = state, .c = ch}; + + curPos.x++; + + if(curPos.x > columnCount){ + curPos.x = 0; + curPos.y++; + Scroll(); + } + + break; + } + } +} + +extern "C" +int main(int argc, char** argv){ + terminalFont = Lemon::Graphics::LoadFont("/initrd/sourcecodepro.ttf", "termmonospace"); + if(!terminalFont){ + terminalFont = Lemon::Graphics::GetFont("default"); + } + + window = new Lemon::GUI::Window("Terminal", {720, 32 * terminalFont->lineHeight}); + + rowCount = window->GetSize().y / terminalFont->lineHeight; + columnCount = 720 / 8; + + curPos = {0, 0}; + + for(int i = 0; i < rowCount; i++){ + buffer.push_back(std::vector()); + } + + + int masterPTYFd; + syscall(SYS_GRANT_PTY, (uintptr_t)&masterPTYFd, 0, 0, 0, 0); + + setenv("TERM", "xterm-256color", 1); // the Lemon OS terminal is (fairly) xterm compatible (256 colour, etc.) + + char* const _argv[] = {const_cast("/system/bin/lsh.lef")}; + lemon_spawn(_argv[0], 1, _argv, 1); + + window->OnPaint = OnPaint; + + char* _buf = (char*)malloc(512); + + winsize wSz = { + .ws_row = static_cast(rowCount), + .ws_col = static_cast(columnCount), + .ws_xpixel = static_cast(window->GetSize().x), + .ws_ypixel = static_cast(window->GetSize().y), + }; + + ioctl(masterPTYFd, TIOCSWINSZ, &wSz); + + std::vector fds; + fds.push_back({.fd = masterPTYFd, .events = POLLIN, .revents = 0}); + + //auto& wMHandler = window->GetHandler(); + //fds.insert(fds.begin(), wMHandler.GetFileDescriptors().begin(), wMHandler.GetFileDescriptors().end()); + for(;;){ + Lemon::LemonEvent ev; + while(window->PollEvent(ev)){ + if(ev.event == Lemon::EventKeyPressed){ + if(ev.key == KEY_ARROW_UP){ + const char* esc = "\e[A"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_ARROW_DOWN){ + const char* esc = "\e[B"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_ARROW_RIGHT){ + const char* esc = "\e[C"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_ARROW_LEFT){ + const char* esc = "\e[D"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_END){ + const char* esc = "\e[F"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_HOME){ + const char* esc = "\e[H"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key == KEY_ESCAPE){ + const char* esc = "\e\e"; + write(masterPTYFd, esc, strlen(esc)); + } else if(ev.key < 128){ + const char key = (char)ev.key; + write(masterPTYFd, &key, 1); + } + } else if (ev.event == Lemon::EventWindowClosed){ + delete window; + exit(0); + return 0; + } else if (ev.event == Lemon::EventWindowResize){ + window->Resize(ev.resizeBounds); + + columnCount = window->GetSize().x / 8; + rowCount = window->GetSize().y / terminalFont->lineHeight; + + wSz.ws_col = static_cast(columnCount); + wSz.ws_row = static_cast(rowCount); + wSz.ws_xpixel = static_cast(window->GetSize().x); + wSz.ws_ypixel = static_cast(window->GetSize().y); + + ioctl(masterPTYFd, TIOCSWINSZ, &wSz); + paintAll = true; + } + } + + while(int len = read(masterPTYFd, _buf, 512)){ + for(int i = 0; i < len; i++){ + PrintChar(_buf[i]); + } + } + + window->Paint(); + + //poll(fds.data(), fds.size(), -1); + } + return 0; +} diff --git a/Applications/meson.build b/Applications/meson.build index 709fcfcd..f989d9d6 100755 --- a/Applications/meson.build +++ b/Applications/meson.build @@ -1,82 +1,82 @@ -project('Lemon Applications', default_options : ['cpp_std=c++17', 'optimization=0', 'warning_level=2', 'werror=true']) - -add_languages('c', 'cpp') -subproject('LemonUtils') - -fileman_src = [ - 'FileManager/main.cpp', -] - -lsh_src = [ - 'LSh/main.cpp', -] - -shell_src = [ - 'Shell/main.cpp', - 'Shell/menu.cpp', - 'Shell/shell.cpp', -] - -snake_src = [ - 'Snake/main.cpp', -] - -terminal_src = [ - 'Terminal/main.cpp', -] - -textedit_src = [ - 'TextEdit/exttextbox.cpp', - 'TextEdit/main.cpp', -] - -sysinfo_src = [ - 'SysInfo/main.cpp', -] - -imgview_src = [ - 'ImgView/main.cpp', -] - -run_src = [ - 'Run/main.cpp', -] - -application_cpp_args = [ - '-Wno-unused-parameter', '-Wno-missing-braces' -] - -guitest_src = [ - 'GUITest/main.cpp', -] - -lemonmonitor_src = [ - 'LemonMonitor/main.cpp', -] - -ipctest_src = [ - 'IPCTest/main.cpp' -] - -jsondump_src = [ - 'JSONDump/main.cpp' -] - -minesweeper_src = [ - 'Minesweeper/main.cpp' -] - -executable('fileman.lef', fileman_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('lsh.lef', lsh_src, cpp_args : application_cpp_args, link_args : ['-llemon'], install : true) -executable('shell.lef', shell_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('snake.lef', snake_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype'], install : true) -executable('terminal.lef', terminal_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype'], install : true) -executable('textedit.lef', textedit_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('imgview.lef', imgview_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('sysinfo.lef', sysinfo_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('guitest.lef', guitest_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('run.lef', run_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('lemonmonitor.lef', lemonmonitor_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) -executable('ipctest.lef', ipctest_src, cpp_args : application_cpp_args, install : true) -executable('jsondump.lef', jsondump_src, cpp_args : application_cpp_args, install : true, link_args : ['-llemon']) -executable('minesweeper.lef', minesweeper_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +project('Lemon Applications', default_options : ['cpp_std=c++17', 'optimization=0', 'warning_level=2', 'werror=true']) + +add_languages('c', 'cpp') +subproject('LemonUtils') + +fileman_src = [ + 'FileManager/main.cpp', +] + +lsh_src = [ + 'LSh/main.cpp', +] + +shell_src = [ + 'Shell/main.cpp', + 'Shell/menu.cpp', + 'Shell/shell.cpp', +] + +snake_src = [ + 'Snake/main.cpp', +] + +terminal_src = [ + 'Terminal/main.cpp', +] + +textedit_src = [ + 'TextEdit/exttextbox.cpp', + 'TextEdit/main.cpp', +] + +sysinfo_src = [ + 'SysInfo/main.cpp', +] + +imgview_src = [ + 'ImgView/main.cpp', +] + +run_src = [ + 'Run/main.cpp', +] + +application_cpp_args = [ + '-Wno-unused-parameter', '-Wno-missing-braces' +] + +guitest_src = [ + 'GUITest/main.cpp', +] + +lemonmonitor_src = [ + 'LemonMonitor/main.cpp', +] + +ipctest_src = [ + 'IPCTest/main.cpp' +] + +jsondump_src = [ + 'JSONDump/main.cpp' +] + +minesweeper_src = [ + 'Minesweeper/main.cpp' +] + +executable('fileman.lef', fileman_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('lsh.lef', lsh_src, cpp_args : application_cpp_args, link_args : ['-llemon'], install : true) +executable('shell.lef', shell_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('snake.lef', snake_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype'], install : true) +executable('terminal.lef', terminal_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype'], install : true) +executable('textedit.lef', textedit_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('imgview.lef', imgview_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('sysinfo.lef', sysinfo_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('guitest.lef', guitest_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('run.lef', run_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('lemonmonitor.lef', lemonmonitor_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) +executable('ipctest.lef', ipctest_src, cpp_args : application_cpp_args, install : true) +executable('jsondump.lef', jsondump_src, cpp_args : application_cpp_args, install : true, link_args : ['-llemon']) +executable('minesweeper.lef', minesweeper_src, cpp_args : application_cpp_args, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install : true) diff --git a/Kernel/include/arch/x86_64/hal.h b/Kernel/include/arch/x86_64/hal.h index d9aa9f4d..7448b517 100755 --- a/Kernel/include/arch/x86_64/hal.h +++ b/Kernel/include/arch/x86_64/hal.h @@ -1,23 +1,23 @@ -#pragma once - -#include - -namespace HAL{ - extern memory_info_t mem_info; - extern video_mode_t videoMode; - extern multiboot2_info_header_t* multibootInfo; - extern uintptr_t multibootModulesAddress; - extern int bootModuleCount; - extern boot_module_t bootModules[]; - extern bool debugMode; - extern bool disableSMP; - extern bool useKCon; - - void InitCore(multiboot2_info_header_t* mb_info); - - void InitVideo(); - - void InitExtra(); - - void Init(multiboot2_info_header_t* mb_info); +#pragma once + +#include + +namespace HAL{ + extern memory_info_t mem_info; + extern video_mode_t videoMode; + extern multiboot2_info_header_t* multibootInfo; + extern uintptr_t multibootModulesAddress; + extern int bootModuleCount; + extern boot_module_t bootModules[]; + extern bool debugMode; + extern bool disableSMP; + extern bool useKCon; + + void InitCore(multiboot2_info_header_t* mb_info); + + void InitVideo(); + + void InitExtra(); + + void Init(multiboot2_info_header_t* mb_info); } \ No newline at end of file diff --git a/Kernel/include/arch/x86_64/idt.h b/Kernel/include/arch/x86_64/idt.h index 43dd18ba..0b2ccf49 100755 --- a/Kernel/include/arch/x86_64/idt.h +++ b/Kernel/include/arch/x86_64/idt.h @@ -1,39 +1,39 @@ -#pragma once - -#include -#include - -#define IRQ0 32 - -#define IPI_HALT 0xFE -#define IPI_SCHEDULE 0xFD - -typedef struct { - uint16_t base_low; - uint16_t sel; - uint8_t ist; - uint8_t flags; - uint16_t base_med; - uint32_t base_high; - uint32_t null; -} __attribute__((packed)) idt_entry_t; - -typedef struct { - uint16_t limit; - uint64_t base; -} __attribute__((packed)) idt_ptr_t; - -typedef void(*isr_t)(void*, regs64_t*); - -extern "C" void idt_flush(); - -namespace IDT{ - void Initialize(); - void RegisterInterruptHandler(uint8_t interrupt, isr_t handler, void* data = nullptr); - - void DisablePIC(); - - uint8_t ReserveUnusedInterrupt(); - - int GetErrCode(); +#pragma once + +#include +#include + +#define IRQ0 32 + +#define IPI_HALT 0xFE +#define IPI_SCHEDULE 0xFD + +typedef struct { + uint16_t base_low; + uint16_t sel; + uint8_t ist; + uint8_t flags; + uint16_t base_med; + uint32_t base_high; + uint32_t null; +} __attribute__((packed)) idt_entry_t; + +typedef struct { + uint16_t limit; + uint64_t base; +} __attribute__((packed)) idt_ptr_t; + +typedef void(*isr_t)(void*, regs64_t*); + +extern "C" void idt_flush(); + +namespace IDT{ + void Initialize(); + void RegisterInterruptHandler(uint8_t interrupt, isr_t handler, void* data = nullptr); + + void DisablePIC(); + + uint8_t ReserveUnusedInterrupt(); + + int GetErrCode(); } \ No newline at end of file diff --git a/Kernel/include/arch/x86_64/system.h b/Kernel/include/arch/x86_64/system.h index 5ca2cb83..1110fae9 100755 --- a/Kernel/include/arch/x86_64/system.h +++ b/Kernel/include/arch/x86_64/system.h @@ -1,63 +1,63 @@ -#pragma once - -//#define KERNEL_VIRTUAL_BASE 0xC0000000 - -#include - -extern "C"{ - void outportb(uint16_t port, uint8_t value); - void outportw(uint16_t port, uint16_t value); - void outportd(uint16_t port, uint32_t value); - void outportl(uint16_t port, uint32_t value); - - uint8_t inportb(uint16_t port); - uint16_t inportw(uint16_t port); - uint32_t inportd(uint16_t port); - uint32_t inportl(uint16_t port); -} - -typedef struct { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rbp; - uint64_t rdi; - uint64_t rsi; - uint64_t rdx; - uint64_t rcx; - uint64_t rbx; - uint64_t rax; - uint64_t rip; - uint64_t cs; - uint64_t rflags; - uint64_t rsp; - uint64_t ss; -} __attribute__((packed)) regs64_t; - -typedef struct { - uint16_t fcw; // FPU Control Word - uint16_t fsw; // FPU Status Word - uint8_t ftw; // FPU Tag Words - uint8_t zero; // Literally just contains a zero - uint16_t fop; // FPU Opcode - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; // SSE Control Register - uint32_t mxcsrMask; // SSE Control Register Mask - uint8_t st[8][16]; // FPU Registers, Last 6 bytes reserved - uint8_t xmm[16][16]; // XMM Registers -} __attribute__((packed)) fx_state_t; - - -static inline int CheckInterrupts(){ - unsigned long flags; - asm volatile ( "pushf;" - "pop %%rax;" - : "=a"(flags) :: "cc" ); - return (flags & 0x200); +#pragma once + +//#define KERNEL_VIRTUAL_BASE 0xC0000000 + +#include + +extern "C"{ + void outportb(uint16_t port, uint8_t value); + void outportw(uint16_t port, uint16_t value); + void outportd(uint16_t port, uint32_t value); + void outportl(uint16_t port, uint32_t value); + + uint8_t inportb(uint16_t port); + uint16_t inportw(uint16_t port); + uint32_t inportd(uint16_t port); + uint32_t inportl(uint16_t port); +} + +typedef struct { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rbp; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} __attribute__((packed)) regs64_t; + +typedef struct { + uint16_t fcw; // FPU Control Word + uint16_t fsw; // FPU Status Word + uint8_t ftw; // FPU Tag Words + uint8_t zero; // Literally just contains a zero + uint16_t fop; // FPU Opcode + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; // SSE Control Register + uint32_t mxcsrMask; // SSE Control Register Mask + uint8_t st[8][16]; // FPU Registers, Last 6 bytes reserved + uint8_t xmm[16][16]; // XMM Registers +} __attribute__((packed)) fx_state_t; + + +static inline int CheckInterrupts(){ + unsigned long flags; + asm volatile ( "pushf;" + "pop %%rax;" + : "=a"(flags) :: "cc" ); + return (flags & 0x200); } \ No newline at end of file diff --git a/Kernel/include/device.h b/Kernel/include/device.h index 177a43ad..c9600e1a 100755 --- a/Kernel/include/device.h +++ b/Kernel/include/device.h @@ -1,109 +1,109 @@ -#pragma once - -#include -#include -#include -#include - -enum DeviceType{ - TypeGenericDevice, - TypeDiskDevice, - TypePartitionDevice, - TypeNetworkAdapterDevice, - TypePseudoterminalDevice, - TypeInputDevice, -}; - -class Device : public FsNode { -public: - Device(DeviceType type){ - name = ""; - - this->type = type; - } - - Device(const char* name, DeviceType type){ - this->name = strdup(name); - this->type = type; - } - - const char* GetName() const{ - return name; - } -protected: - void SetName(const char* name){ - this->name = strdup(name); - } - - void SetDescription(const char* desc){ - this->description = strdup(desc); - } - - char* name = ""; - char* description = nullptr; - DeviceType type = TypeGenericDevice; -}; - -class PartitionDevice; - -class DiskDevice : public Device{ - friend class PartitionDevice; -protected: - int nextPartitionNumber = 0; -public: - DiskDevice(); - - int InitializePartitions(); - - virtual int ReadDiskBlock(uint64_t lba, uint32_t count, void* buffer); - virtual int WriteDiskBlock(uint64_t lba, uint32_t count, void* buffer); - - virtual ssize_t Read(size_t off, size_t size, uint8_t* buffer); - virtual ssize_t Write(size_t off, size_t size, uint8_t* buffer); - - virtual ~DiskDevice(); - - List partitions; - int blocksize = 512; -private: -}; - -class PartitionDevice : public Device{ -public: - PartitionDevice(uint64_t startLBA, uint64_t endLBA, DiskDevice* disk); - - virtual int ReadAbsolute(uint64_t off, uint32_t count, void* buffer); - virtual int ReadBlock(uint64_t lba, uint32_t count, void* buffer); - virtual int WriteBlock(uint64_t lba, uint32_t count, void* buffer); - - virtual ~PartitionDevice(); - - DiskDevice* parentDisk; -private: - - uint64_t startLBA; - uint64_t endLBA; -}; - -namespace DeviceManager{ - ///////////////////////////// - /// \brief Initialize basic devices (null, urandom, etc.) - ///////////////////////////// - void InitializeBasicDevices(); - - ///////////////////////////// - /// \brief Register a device - /// - /// Add device to devfs - /// - /// \param dev reference to Device to add - ///////////////////////////// - void RegisterDevice(Device& dev); - - ///////////////////////////// - /// \brief Get devfs - /// - /// \return FsNode* object representing devfs root - ///////////////////////////// - FsNode* GetDevFS(); +#pragma once + +#include +#include +#include +#include + +enum DeviceType{ + TypeGenericDevice, + TypeDiskDevice, + TypePartitionDevice, + TypeNetworkAdapterDevice, + TypePseudoterminalDevice, + TypeInputDevice, +}; + +class Device : public FsNode { +public: + Device(DeviceType type){ + name = ""; + + this->type = type; + } + + Device(const char* name, DeviceType type){ + this->name = strdup(name); + this->type = type; + } + + const char* GetName() const{ + return name; + } +protected: + void SetName(const char* name){ + this->name = strdup(name); + } + + void SetDescription(const char* desc){ + this->description = strdup(desc); + } + + char* name = ""; + char* description = nullptr; + DeviceType type = TypeGenericDevice; +}; + +class PartitionDevice; + +class DiskDevice : public Device{ + friend class PartitionDevice; +protected: + int nextPartitionNumber = 0; +public: + DiskDevice(); + + int InitializePartitions(); + + virtual int ReadDiskBlock(uint64_t lba, uint32_t count, void* buffer); + virtual int WriteDiskBlock(uint64_t lba, uint32_t count, void* buffer); + + virtual ssize_t Read(size_t off, size_t size, uint8_t* buffer); + virtual ssize_t Write(size_t off, size_t size, uint8_t* buffer); + + virtual ~DiskDevice(); + + List partitions; + int blocksize = 512; +private: +}; + +class PartitionDevice : public Device{ +public: + PartitionDevice(uint64_t startLBA, uint64_t endLBA, DiskDevice* disk); + + virtual int ReadAbsolute(uint64_t off, uint32_t count, void* buffer); + virtual int ReadBlock(uint64_t lba, uint32_t count, void* buffer); + virtual int WriteBlock(uint64_t lba, uint32_t count, void* buffer); + + virtual ~PartitionDevice(); + + DiskDevice* parentDisk; +private: + + uint64_t startLBA; + uint64_t endLBA; +}; + +namespace DeviceManager{ + ///////////////////////////// + /// \brief Initialize basic devices (null, urandom, etc.) + ///////////////////////////// + void InitializeBasicDevices(); + + ///////////////////////////// + /// \brief Register a device + /// + /// Add device to devfs + /// + /// \param dev reference to Device to add + ///////////////////////////// + void RegisterDevice(Device& dev); + + ///////////////////////////// + /// \brief Get devfs + /// + /// \return FsNode* object representing devfs root + ///////////////////////////// + FsNode* GetDevFS(); } \ No newline at end of file diff --git a/Kernel/include/devicemanager.h b/Kernel/include/devicemanager.h index 4f9c8e26..1f0c9bba 100755 --- a/Kernel/include/devicemanager.h +++ b/Kernel/include/devicemanager.h @@ -1,9 +1,9 @@ -#pragma once - -#include -#include - -namespace DeviceManager{ - - void Init(); +#pragma once + +#include +#include + +namespace DeviceManager{ + + void Init(); } \ No newline at end of file diff --git a/Kernel/include/fs/fat32.h b/Kernel/include/fs/fat32.h index 418ebd59..35ab0a3c 100755 --- a/Kernel/include/fs/fat32.h +++ b/Kernel/include/fs/fat32.h @@ -1,153 +1,153 @@ -#pragma once - -#include -#include -#include -#include -#include - -#define FAT_ATTR_READ_ONLY 0x1 -#define FAT_ATTR_HIDDEN 0x2 -#define FAT_ATTR_SYSTEM 0x4 -#define FAT_ATTR_VOLUME_ID 0x8 -#define FAT_ATTR_DIRECTORY 0x10 -#define FAT_ATTR_ARCHIVE 0x20 - -typedef struct { - uint8_t jmp[3]; // Can be ignored - int8_t oem[8]; // OEM identifier - uint16_t bytesPerSector; // Bytes per sector - uint8_t sectorsPerCluster; // Sectors per cluster - uint16_t reservedSectors; // Reserved sectors count - uint8_t fatCount; // Number of File Allocation Tables - uint16_t directoryEntries; // Number of directory entries - uint16_t volSectorCount; // FAT12/16 only - uint8_t mediaDescriptorType; // Media Descriptor Type - uint16_t sectorsPerFAT; // FAT12/16 only - uint16_t sectorsPerTrack; // Sectors per track - uint16_t headCount; // Number of heads on the storage device - uint32_t hiddenSectorCount; // Number of hidden sectors - uint32_t largeSectorCount; // Large sector count -} __attribute__((packed)) fat_bpb_t; // BIOS Parameter Block - -typedef struct { - uint32_t sectorsPerFAT; // Sectors per FAT - uint16_t flags; // Flags - uint16_t fatVersion; // FAT version number - uint32_t rootClusterNum; // Cluster number of the root directory - uint16_t fsInfoSector; // Sector number of the FSInfo structure - uint16_t bkupBootSector; // Number of the backup boot sector - uint8_t reserved[12]; // Reserved - uint8_t driveNum; // 0x0 for floppy, 0x80 for hard disk - uint8_t reserved1; // Reserved - uint8_t signature; // Should be 0x28 or 0x29 - uint32_t volumeID; // Volume ID number - int8_t volumeLabelString[11]; // Volume label string - int8_t sysIdString[8]; // System identifier string ("FAT32 ") -} __attribute__((packed)) fat32_ebr_t; // FAT32 Extended Boot Record - -typedef struct { - fat_bpb_t bpb; - fat32_ebr_t ebr; -} __attribute__((packed)) fat32_boot_record_t; - -typedef struct { - uint32_t leadSignature; // Should be 0x41615252 - uint8_t reserved[480]; - uint64_t signature; // Should be 0x61417272 - uint32_t freeClusterCount; // Last known free cluster count, if 0xFFFFFFFF then free clusters need to be recalculated, check if fits in cluster count - uint32_t firstSearchCluster; // Search for free clusters from here, if 0xFFFFFFFF then from cluster 2, check if fits in cluster count - uint8_t reserved2[12]; - uint16_t trailSignature; // Should be 0xAA55 -} __attribute__((packed)) fat32_fsinfo_t; // FAT32 FSInfo Structure - -typedef struct -{ - uint8_t filename[8]; - uint8_t ext[3]; - uint8_t attributes; - uint8_t reserved; - uint8_t createTimeTenthsOfSecond; - uint16_t creationTime; - uint16_t creationDate; - uint16_t accessedDate; - uint16_t highClusterNum; - uint16_t modificationTime; - uint16_t modificationDate; - uint16_t lowClusterNum; - uint32_t fileSize; -} __attribute__((packed)) fat_entry_t; - -typedef struct -{ - uint8_t order; - uint16_t characters0[5]; - uint8_t attributes; - uint8_t type; - uint8_t checksum; - uint16_t characters1[6]; - uint16_t zero; - uint16_t characters2[2]; -} __attribute__((packed)) fat_lfn_entry_t; // Long File Name - -namespace fs::FAT32{ - class Fat32Volume; - - class Fat32Node : public FsNode { - public: - ssize_t Read(size_t, size_t, uint8_t *); - ssize_t Write(size_t, size_t, uint8_t *); - //fs_fd_t* Open(size_t flags); - //void Close(); - int ReadDir(DirectoryEntry*, uint32_t); - FsNode* FindDir(char* name); - - Fat32Volume* vol; - }; - - class Fat32Volume : public FsVolume { - public: - Fat32Volume(PartitionDevice* part, char* name); - - ssize_t Read(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer); - ssize_t Write(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer); - void Open(Fat32Node* node, uint32_t flags); - void Close(Fat32Node* node); - int ReadDir(Fat32Node* node, DirectoryEntry* dirent, uint32_t index); - FsNode* FindDir(Fat32Node* node, char* name); - - private: - uint64_t ClusterToLBA(uint32_t cluster); - List* GetClusterChain(uint32_t cluster); - void* ReadClusterChain(uint32_t cluster, int* count); - void* ReadClusterChain(uint32_t cluster, int* count, size_t max); - - PartitionDevice* part; - fat32_boot_record_t* bootRecord; - - int clusterSizeBytes; - Fat32Node fat32MountPoint; - }; - - int Identify(PartitionDevice* part); - - inline void GetLongFilename(char* name, fat_lfn_entry_t** lfnEntries, int lfnCount){ - int nameIndex = 0; - for(int i = 0; i < lfnCount; i++){ - fat_lfn_entry_t* ent = lfnEntries[i]; - - for(int j = 0; j < 5; j++){ - name[nameIndex++] = ent->characters0[j]; - } - - for(int j = 0; j < 6; j++){ - name[nameIndex++] = ent->characters1[j]; - } - - name[nameIndex++] = ent->characters2[0]; - name[nameIndex++] = ent->characters2[1]; - name[nameIndex++] = 0; - name[nameIndex++] = 0; - } - } +#pragma once + +#include +#include +#include +#include +#include + +#define FAT_ATTR_READ_ONLY 0x1 +#define FAT_ATTR_HIDDEN 0x2 +#define FAT_ATTR_SYSTEM 0x4 +#define FAT_ATTR_VOLUME_ID 0x8 +#define FAT_ATTR_DIRECTORY 0x10 +#define FAT_ATTR_ARCHIVE 0x20 + +typedef struct { + uint8_t jmp[3]; // Can be ignored + int8_t oem[8]; // OEM identifier + uint16_t bytesPerSector; // Bytes per sector + uint8_t sectorsPerCluster; // Sectors per cluster + uint16_t reservedSectors; // Reserved sectors count + uint8_t fatCount; // Number of File Allocation Tables + uint16_t directoryEntries; // Number of directory entries + uint16_t volSectorCount; // FAT12/16 only + uint8_t mediaDescriptorType; // Media Descriptor Type + uint16_t sectorsPerFAT; // FAT12/16 only + uint16_t sectorsPerTrack; // Sectors per track + uint16_t headCount; // Number of heads on the storage device + uint32_t hiddenSectorCount; // Number of hidden sectors + uint32_t largeSectorCount; // Large sector count +} __attribute__((packed)) fat_bpb_t; // BIOS Parameter Block + +typedef struct { + uint32_t sectorsPerFAT; // Sectors per FAT + uint16_t flags; // Flags + uint16_t fatVersion; // FAT version number + uint32_t rootClusterNum; // Cluster number of the root directory + uint16_t fsInfoSector; // Sector number of the FSInfo structure + uint16_t bkupBootSector; // Number of the backup boot sector + uint8_t reserved[12]; // Reserved + uint8_t driveNum; // 0x0 for floppy, 0x80 for hard disk + uint8_t reserved1; // Reserved + uint8_t signature; // Should be 0x28 or 0x29 + uint32_t volumeID; // Volume ID number + int8_t volumeLabelString[11]; // Volume label string + int8_t sysIdString[8]; // System identifier string ("FAT32 ") +} __attribute__((packed)) fat32_ebr_t; // FAT32 Extended Boot Record + +typedef struct { + fat_bpb_t bpb; + fat32_ebr_t ebr; +} __attribute__((packed)) fat32_boot_record_t; + +typedef struct { + uint32_t leadSignature; // Should be 0x41615252 + uint8_t reserved[480]; + uint64_t signature; // Should be 0x61417272 + uint32_t freeClusterCount; // Last known free cluster count, if 0xFFFFFFFF then free clusters need to be recalculated, check if fits in cluster count + uint32_t firstSearchCluster; // Search for free clusters from here, if 0xFFFFFFFF then from cluster 2, check if fits in cluster count + uint8_t reserved2[12]; + uint16_t trailSignature; // Should be 0xAA55 +} __attribute__((packed)) fat32_fsinfo_t; // FAT32 FSInfo Structure + +typedef struct +{ + uint8_t filename[8]; + uint8_t ext[3]; + uint8_t attributes; + uint8_t reserved; + uint8_t createTimeTenthsOfSecond; + uint16_t creationTime; + uint16_t creationDate; + uint16_t accessedDate; + uint16_t highClusterNum; + uint16_t modificationTime; + uint16_t modificationDate; + uint16_t lowClusterNum; + uint32_t fileSize; +} __attribute__((packed)) fat_entry_t; + +typedef struct +{ + uint8_t order; + uint16_t characters0[5]; + uint8_t attributes; + uint8_t type; + uint8_t checksum; + uint16_t characters1[6]; + uint16_t zero; + uint16_t characters2[2]; +} __attribute__((packed)) fat_lfn_entry_t; // Long File Name + +namespace fs::FAT32{ + class Fat32Volume; + + class Fat32Node : public FsNode { + public: + ssize_t Read(size_t, size_t, uint8_t *); + ssize_t Write(size_t, size_t, uint8_t *); + //fs_fd_t* Open(size_t flags); + //void Close(); + int ReadDir(DirectoryEntry*, uint32_t); + FsNode* FindDir(char* name); + + Fat32Volume* vol; + }; + + class Fat32Volume : public FsVolume { + public: + Fat32Volume(PartitionDevice* part, char* name); + + ssize_t Read(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer); + ssize_t Write(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer); + void Open(Fat32Node* node, uint32_t flags); + void Close(Fat32Node* node); + int ReadDir(Fat32Node* node, DirectoryEntry* dirent, uint32_t index); + FsNode* FindDir(Fat32Node* node, char* name); + + private: + uint64_t ClusterToLBA(uint32_t cluster); + List* GetClusterChain(uint32_t cluster); + void* ReadClusterChain(uint32_t cluster, int* count); + void* ReadClusterChain(uint32_t cluster, int* count, size_t max); + + PartitionDevice* part; + fat32_boot_record_t* bootRecord; + + int clusterSizeBytes; + Fat32Node fat32MountPoint; + }; + + int Identify(PartitionDevice* part); + + inline void GetLongFilename(char* name, fat_lfn_entry_t** lfnEntries, int lfnCount){ + int nameIndex = 0; + for(int i = 0; i < lfnCount; i++){ + fat_lfn_entry_t* ent = lfnEntries[i]; + + for(int j = 0; j < 5; j++){ + name[nameIndex++] = ent->characters0[j]; + } + + for(int j = 0; j < 6; j++){ + name[nameIndex++] = ent->characters1[j]; + } + + name[nameIndex++] = ent->characters2[0]; + name[nameIndex++] = ent->characters2[1]; + name[nameIndex++] = 0; + name[nameIndex++] = 0; + } + } } \ No newline at end of file diff --git a/Kernel/include/fs/fsvolume.h b/Kernel/include/fs/fsvolume.h index 45ded5bd..a3f2ae67 100755 --- a/Kernel/include/fs/fsvolume.h +++ b/Kernel/include/fs/fsvolume.h @@ -1,30 +1,30 @@ -#pragma once - -#include - -namespace fs{ - - class FsVolume{ - public: - volume_id_t volumeID; - FsNode* mountPoint; - DirectoryEntry mountPointDirent; - }; - - class LinkVolume : public FsVolume{ - public: - LinkVolume(FsVolume* link, char* name){ - strcpy(mountPointDirent.name, name); - mountPointDirent.node = link->mountPoint; - mountPointDirent.flags = link->mountPointDirent.flags; - mountPointDirent.node->nlink++; - } - - LinkVolume(FsNode* link, char* name){ - strcpy(mountPointDirent.name, name); - mountPointDirent.node = link; - mountPointDirent.flags = DT_DIR; - mountPointDirent.node->nlink++; - } - }; +#pragma once + +#include + +namespace fs{ + + class FsVolume{ + public: + volume_id_t volumeID; + FsNode* mountPoint; + DirectoryEntry mountPointDirent; + }; + + class LinkVolume : public FsVolume{ + public: + LinkVolume(FsVolume* link, char* name){ + strcpy(mountPointDirent.name, name); + mountPointDirent.node = link->mountPoint; + mountPointDirent.flags = link->mountPointDirent.flags; + mountPointDirent.node->nlink++; + } + + LinkVolume(FsNode* link, char* name){ + strcpy(mountPointDirent.name, name); + mountPointDirent.node = link; + mountPointDirent.flags = DT_DIR; + mountPointDirent.node->nlink++; + } + }; } \ No newline at end of file diff --git a/Kernel/include/gpt.h b/Kernel/include/gpt.h index 72ec6a24..4bfd65b0 100755 --- a/Kernel/include/gpt.h +++ b/Kernel/include/gpt.h @@ -1,36 +1,36 @@ -#pragma once - -#include -#include - -#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL - -typedef struct{ - uint64_t signature; - uint32_t revision; - uint32_t size; - uint32_t crc32; - uint32_t reserved; - uint64_t currentLBA; - uint64_t backupLBA; - uint64_t firstLBA; - uint64_t lastLBA; - uint8_t diskGUID[16]; - uint64_t partitionTableLBA; - uint32_t partNum; - uint32_t partEntrySize; - uint32_t partEntriesCRC; -} __attribute__((packed)) gpt_header_t; - -typedef struct{ - uint8_t typeGUID[16]; - uint8_t partitionGUID[16]; - uint64_t startLBA; - uint64_t endLBA; - uint64_t flags; - uint8_t name[72]; -} __attribute__((packed)) gpt_entry_t; - -namespace GPT{ - int Parse(DiskDevice* disk); +#pragma once + +#include +#include + +#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL + +typedef struct{ + uint64_t signature; + uint32_t revision; + uint32_t size; + uint32_t crc32; + uint32_t reserved; + uint64_t currentLBA; + uint64_t backupLBA; + uint64_t firstLBA; + uint64_t lastLBA; + uint8_t diskGUID[16]; + uint64_t partitionTableLBA; + uint32_t partNum; + uint32_t partEntrySize; + uint32_t partEntriesCRC; +} __attribute__((packed)) gpt_header_t; + +typedef struct{ + uint8_t typeGUID[16]; + uint8_t partitionGUID[16]; + uint64_t startLBA; + uint64_t endLBA; + uint64_t flags; + uint8_t name[72]; +} __attribute__((packed)) gpt_entry_t; + +namespace GPT{ + int Parse(DiskDevice* disk); } \ No newline at end of file diff --git a/Kernel/include/mischdr.h b/Kernel/include/mischdr.h index 5eba292e..f80a9627 100755 --- a/Kernel/include/mischdr.h +++ b/Kernel/include/mischdr.h @@ -1,212 +1,212 @@ -#pragma once - -#include -#include - -#define MULTIBOOT2_TAG_ALIGN 8 - -typedef struct { - uint32_t flags; - uint32_t memoryLo; - uint32_t memoryHi; - uint32_t bootDevice; - uint32_t cmdline; - uint32_t modsCount; - uint32_t modsAddr; - uint32_t num; - uint32_t size; - uint32_t addr; - uint32_t shndx; - uint32_t mmapLength; - uint32_t mmapAddr; - uint32_t drivesLength; - uint32_t drivesAddr; - uint32_t configTable; - uint32_t bootloaderName; - uint32_t apmTable; - - uint32_t vbeControlInfo; - uint32_t vbeModeInfo; - uint16_t vbeMode; - uint16_t vbeInterfaceSeg; - uint16_t vbeInterfaceOff; - uint16_t vbeInterfaceLen; - - uint64_t framebufferAddr; - uint32_t framebufferPitch; - uint32_t framebufferWidth; - uint32_t framebufferHeight; - uint8_t framebufferBpp; - uint8_t framebufferType; -}__attribute__ ((packed)) multiboot1_info_t; - -typedef struct -{ - uint32_t mod_start; - uint32_t mod_end; - uint32_t string; - uint32_t reserved; -}__attribute__((packed)) multiboot1_module_t; - -typedef struct -{ - uint32_t size; - uint64_t base; - uint64_t length; - uint32_t type; -} __attribute__((packed)) multiboot1_memory_map_t; - -enum { - Mboot2CmdLine = 1, - Mboot2BootloaderName = 2, - Mboot2Modules = 3, - Mboot2MemoryInfo = 4, - Mboot2BIOSBootDevice = 5, - Mboot2MemoryMap = 6, - Mboot2VBEInfo = 7, - Mboot2FramebufferInfo = 8, - Mboot2ELFSymbols = 9, - Mboot2APMTable = 10, - Mboot2EFISystemTable32 = 11, - Mboot2EFISystemTable64 = 12, - Mboot2SMBIOSTables = 13, - Mboot2ACPI1RSDP = 14, - Mboot2ACPI2RSDP = 15, - Mboot2NetInfo = 16, - Mboot2EFIMemoryMap = 17, - Mboot2EFIBootServices = 18, - Mboot2EFIImageHandle32 = 19, - Mboot2EFIImageHandle64 = 20, - Mboot2ImageLoadBase = 21, -}; - -typedef struct{ - uint32_t totalSize; - uint32_t reserved; - uint8_t tags[]; -} __attribute__((packed)) multiboot2_info_header_t; - -typedef struct mb2tag{ - uint32_t type; - uint32_t size; - uint8_t tag[]; - - mb2tag* next(){ - return reinterpret_cast(((uintptr_t)this) + ((size + MULTIBOOT2_TAG_ALIGN - 1) & ~(MULTIBOOT2_TAG_ALIGN - 1))); // Get next tag making sure to round up to alignment - } -} __attribute__((packed)) multiboot2_tag_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2Modules; - uint32_t size; - uint32_t moduleStart; - uint32_t moduleEnd; - char string[]; - }; -} __attribute__((packed)) multiboot2_module_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2MemoryInfo; - uint32_t size; - - uint32_t memoryLower; - uint32_t memoryUpper; - }; - } __attribute__((packed)) multiboot2_memory_info_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2CmdLine; - uint32_t size; - char string[]; - }; -} __attribute__((packed)) multiboot2_cmdline_t; - -typedef struct { - uint64_t base; - uint64_t length; - uint32_t type; - uint32_t reserved; -} __attribute__((packed)) multiboot2_mmap_entry_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2MemoryMap; - uint32_t size; - - uint32_t entrySize; // Size of each entry - uint32_t entryVersion; - - multiboot2_mmap_entry_t entries[]; - }; -} __attribute__((packed)) multiboot2_memory_map_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2ACPI1RSDP; - uint32_t size; - struct acpi_xsdp_t rsdp; - }; -} __attribute__((packed)) multiboot2_acpi1_rsdp_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2ACPI2RSDP; - uint32_t size; - struct acpi_xsdp_t rsdp; - }; -} __attribute__((packed)) multiboot2_acpi2_rsdp_t; - -typedef union { - multiboot2_tag_t tag; - struct{ - uint32_t type = Mboot2FramebufferInfo; - uint32_t size; - - uint64_t framebufferAddr; - uint32_t framebufferPitch; - uint32_t framebufferWidth; - uint32_t framebufferHeight; - uint8_t framebufferBpp; - uint8_t framebufferType; - uint8_t reserved; - }; - - // There is extra colour info here that we ignore for now -} __attribute__((packed)) multiboot2_framebuffer_info_t; - -enum { - VideoModeIndexed = 0, - VideoModeRGB = 1, - VideoModeText = 2, -}; - -typedef struct{ - uint32_t width; // Resolution width - uint32_t height; // Resolution height - uint16_t bpp; // Resolution depth/bits per pixel - - uint32_t pitch; // Video mode pitch - - void* address; // Video memory address - uintptr_t physicalAddress; - - int type; -} video_mode_t; - -typedef struct { - uintptr_t totalMemory; -} memory_info_t; - -typedef struct { - uintptr_t base; - uintptr_t size; +#pragma once + +#include +#include + +#define MULTIBOOT2_TAG_ALIGN 8 + +typedef struct { + uint32_t flags; + uint32_t memoryLo; + uint32_t memoryHi; + uint32_t bootDevice; + uint32_t cmdline; + uint32_t modsCount; + uint32_t modsAddr; + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; + uint32_t mmapLength; + uint32_t mmapAddr; + uint32_t drivesLength; + uint32_t drivesAddr; + uint32_t configTable; + uint32_t bootloaderName; + uint32_t apmTable; + + uint32_t vbeControlInfo; + uint32_t vbeModeInfo; + uint16_t vbeMode; + uint16_t vbeInterfaceSeg; + uint16_t vbeInterfaceOff; + uint16_t vbeInterfaceLen; + + uint64_t framebufferAddr; + uint32_t framebufferPitch; + uint32_t framebufferWidth; + uint32_t framebufferHeight; + uint8_t framebufferBpp; + uint8_t framebufferType; +}__attribute__ ((packed)) multiboot1_info_t; + +typedef struct +{ + uint32_t mod_start; + uint32_t mod_end; + uint32_t string; + uint32_t reserved; +}__attribute__((packed)) multiboot1_module_t; + +typedef struct +{ + uint32_t size; + uint64_t base; + uint64_t length; + uint32_t type; +} __attribute__((packed)) multiboot1_memory_map_t; + +enum { + Mboot2CmdLine = 1, + Mboot2BootloaderName = 2, + Mboot2Modules = 3, + Mboot2MemoryInfo = 4, + Mboot2BIOSBootDevice = 5, + Mboot2MemoryMap = 6, + Mboot2VBEInfo = 7, + Mboot2FramebufferInfo = 8, + Mboot2ELFSymbols = 9, + Mboot2APMTable = 10, + Mboot2EFISystemTable32 = 11, + Mboot2EFISystemTable64 = 12, + Mboot2SMBIOSTables = 13, + Mboot2ACPI1RSDP = 14, + Mboot2ACPI2RSDP = 15, + Mboot2NetInfo = 16, + Mboot2EFIMemoryMap = 17, + Mboot2EFIBootServices = 18, + Mboot2EFIImageHandle32 = 19, + Mboot2EFIImageHandle64 = 20, + Mboot2ImageLoadBase = 21, +}; + +typedef struct{ + uint32_t totalSize; + uint32_t reserved; + uint8_t tags[]; +} __attribute__((packed)) multiboot2_info_header_t; + +typedef struct mb2tag{ + uint32_t type; + uint32_t size; + uint8_t tag[]; + + mb2tag* next(){ + return reinterpret_cast(((uintptr_t)this) + ((size + MULTIBOOT2_TAG_ALIGN - 1) & ~(MULTIBOOT2_TAG_ALIGN - 1))); // Get next tag making sure to round up to alignment + } +} __attribute__((packed)) multiboot2_tag_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2Modules; + uint32_t size; + uint32_t moduleStart; + uint32_t moduleEnd; + char string[]; + }; +} __attribute__((packed)) multiboot2_module_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2MemoryInfo; + uint32_t size; + + uint32_t memoryLower; + uint32_t memoryUpper; + }; + } __attribute__((packed)) multiboot2_memory_info_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2CmdLine; + uint32_t size; + char string[]; + }; +} __attribute__((packed)) multiboot2_cmdline_t; + +typedef struct { + uint64_t base; + uint64_t length; + uint32_t type; + uint32_t reserved; +} __attribute__((packed)) multiboot2_mmap_entry_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2MemoryMap; + uint32_t size; + + uint32_t entrySize; // Size of each entry + uint32_t entryVersion; + + multiboot2_mmap_entry_t entries[]; + }; +} __attribute__((packed)) multiboot2_memory_map_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2ACPI1RSDP; + uint32_t size; + struct acpi_xsdp_t rsdp; + }; +} __attribute__((packed)) multiboot2_acpi1_rsdp_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2ACPI2RSDP; + uint32_t size; + struct acpi_xsdp_t rsdp; + }; +} __attribute__((packed)) multiboot2_acpi2_rsdp_t; + +typedef union { + multiboot2_tag_t tag; + struct{ + uint32_t type = Mboot2FramebufferInfo; + uint32_t size; + + uint64_t framebufferAddr; + uint32_t framebufferPitch; + uint32_t framebufferWidth; + uint32_t framebufferHeight; + uint8_t framebufferBpp; + uint8_t framebufferType; + uint8_t reserved; + }; + + // There is extra colour info here that we ignore for now +} __attribute__((packed)) multiboot2_framebuffer_info_t; + +enum { + VideoModeIndexed = 0, + VideoModeRGB = 1, + VideoModeText = 2, +}; + +typedef struct{ + uint32_t width; // Resolution width + uint32_t height; // Resolution height + uint16_t bpp; // Resolution depth/bits per pixel + + uint32_t pitch; // Video mode pitch + + void* address; // Video memory address + uintptr_t physicalAddress; + + int type; +} video_mode_t; + +typedef struct { + uintptr_t totalMemory; +} memory_info_t; + +typedef struct { + uintptr_t base; + uintptr_t size; } boot_module_t; \ No newline at end of file diff --git a/Kernel/include/net/socket.h b/Kernel/include/net/socket.h index 2637e523..9264fa59 100755 --- a/Kernel/include/net/socket.h +++ b/Kernel/include/net/socket.h @@ -1,221 +1,221 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#define MSG_CTRUNC 0x1 -#define MSG_DONTROUTE 0x2 -#define MSG_EOR 0x4 -#define MSG_OOB 0x8 -#define MSG_NOSIGNAL 0x10 -#define MSG_PEEK 0x20 -#define MSG_TRUNC 0x40 -#define MSG_WAITALL 0x80 -#define MSG_DONTWAIT 0x1000 - -#define CONNECTION_BACKLOG 128 - -#define SOCK_NONBLOCK 0x10000 - -#define STREAM_MAX_BUFSIZE 0x20000 // 128 KB - -typedef unsigned int sa_family_t; -typedef uint32_t socklen_t; - -typedef struct sockaddr { - sa_family_t family; - char data[14]; -} sockaddr_t; - -struct sockaddr_un { - sa_family_t sun_family; /* AF_UNIX */ - char sun_path[108]; /* Pathname */ -}; - -struct in_addr { - uint32_t s_addr; -}; - -struct sockaddr_in { - sa_family_t sin_family; - unsigned short sin_port; - struct in_addr in_addr; - char sin_zero[8]; -}; - -struct iovec { - void* base; - size_t len; -}; - -struct msghdr { - void* name; - socklen_t namelen; - struct iovec* iov; - size_t iovlen; - void* control; - size_t controllen; - int flags; -}; - -struct poll { - int fd; - short events; - short returnedEvents; -}; - -class Socket; - -struct SocketConnection { - Socket* socket; - int connectionType; -}; - -enum { - StreamSocket = 4, - DatagramSocket = 1, - SequencedSocket = 3, - RawSocket = 0x10000, - ReliableDatagramSocket = 0x20000, - // Packet is considered obsolete -}; - -enum { - InternetProtocol = 1, - InternetProtocol6 = 2, - UnixDomain = 3, - LocalDomain = 3, -}; - -enum { - ClientRole, - ServerRole, -}; - -class Socket : public FsNode { -protected: - int type = 0; // Type (Stream, Datagram, etc.) - int domain = 0; // Domain (UNIX, INET, etc.) - Semaphore pendingConnections = Semaphore(CONNECTION_BACKLOG); // Pending Connections semaphore - List pending; // Pending Connections - - bool bound = false; // Has it been bound to an address> - bool passive = false; // Listening? - bool blocking = true; -public: - bool connected = false; // Connected? - int role; // Server/Client - - static Socket* CreateSocket(int domain, int type, int protocol); - - Socket(int type, int protocol); - virtual ~Socket(); - - virtual Socket* Accept(sockaddr* addr, socklen_t* addrlen); - virtual Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); - virtual int Bind(const sockaddr* addr, socklen_t addrlen); - virtual int Connect(const sockaddr* addr, socklen_t addrlen); - virtual int Listen(int backlog); - - virtual int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); - virtual int64_t Receive(void* buffer, size_t len, int flags); - virtual ssize_t Read(size_t offset, size_t size, uint8_t* buffer); - - virtual int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); - virtual int64_t Send(void* buffer, size_t len, int flags); - virtual ssize_t Write(size_t offset, size_t size, uint8_t* buffer); - - virtual fs_fd_t* Open(size_t flags); - virtual void Close(); - - virtual void Watch(FilesystemWatcher& watcher, int events); - virtual void Unwatch(FilesystemWatcher& watcher); - - virtual int GetDomain() { return domain; } - virtual int IsListening() { return passive; } - virtual int IsBlocking() { return blocking; } - virtual int IsConnected() { return connected; } - - virtual int PendingConnections() { return pending.get_length(); } -}; - -class LocalSocket : public Socket { - lock_t slock = 0; - - lock_t watcherLock = 0; - List watching; -public: - LocalSocket* peer = nullptr; - - Stream* inbound = nullptr; - Stream* outbound = nullptr; - - LocalSocket(int type, int protocol); - - int ConnectTo(Socket* client); - void DisconnectPeer(); - - void OnDisconnect(); - - Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); - int Bind(const sockaddr* addr, socklen_t addrlen); - int Connect(const sockaddr* addr, socklen_t addrlen); - int Listen(int backlog); - - fs_fd_t* Open(size_t flags); - void Close(); - - int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); - int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); - - void Watch(FilesystemWatcher& watcher, int events); - void Unwatch(FilesystemWatcher& watcher); - - bool CanRead() { if(inbound) return !inbound->Empty(); else return false; } -}; - -class IPSocket : public Socket { -protected: - IPv4Address address = 0; - BigEndian port = 0; - BigEndian destinationPort = 0; - - List pQueue; - - virtual int64_t IPReceiveFrom(void* buffer, size_t len); -public: - IPSocket(int type, int protocol); - virtual ~IPSocket(); - - Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); - int Bind(const sockaddr* addr, socklen_t addrlen); - int Connect(const sockaddr* addr, socklen_t addrlen); - int Listen(int backlog); - - void Close(); - - int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); - virtual int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); -}; - -class UDPSocket : public IPSocket { - int64_t IPReceiveFrom(void* buffer, size_t len); -public: - UDPSocket(int type, int protocol); - int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); -}; - -namespace SocketManager{ - typedef struct SocketBinding{ - char* address; - Socket* socket; - } sock_binding_t; - - Socket* ResolveSocketAddress(const sockaddr* addr, socklen_t addrlen); - int BindSocket(Socket* sock, const sockaddr* addr, socklen_t addrlen); - void DestroySocket(Socket* sock); +#pragma once + +#include +#include +#include +#include +#include +#include + +#define MSG_CTRUNC 0x1 +#define MSG_DONTROUTE 0x2 +#define MSG_EOR 0x4 +#define MSG_OOB 0x8 +#define MSG_NOSIGNAL 0x10 +#define MSG_PEEK 0x20 +#define MSG_TRUNC 0x40 +#define MSG_WAITALL 0x80 +#define MSG_DONTWAIT 0x1000 + +#define CONNECTION_BACKLOG 128 + +#define SOCK_NONBLOCK 0x10000 + +#define STREAM_MAX_BUFSIZE 0x20000 // 128 KB + +typedef unsigned int sa_family_t; +typedef uint32_t socklen_t; + +typedef struct sockaddr { + sa_family_t family; + char data[14]; +} sockaddr_t; + +struct sockaddr_un { + sa_family_t sun_family; /* AF_UNIX */ + char sun_path[108]; /* Pathname */ +}; + +struct in_addr { + uint32_t s_addr; +}; + +struct sockaddr_in { + sa_family_t sin_family; + unsigned short sin_port; + struct in_addr in_addr; + char sin_zero[8]; +}; + +struct iovec { + void* base; + size_t len; +}; + +struct msghdr { + void* name; + socklen_t namelen; + struct iovec* iov; + size_t iovlen; + void* control; + size_t controllen; + int flags; +}; + +struct poll { + int fd; + short events; + short returnedEvents; +}; + +class Socket; + +struct SocketConnection { + Socket* socket; + int connectionType; +}; + +enum { + StreamSocket = 4, + DatagramSocket = 1, + SequencedSocket = 3, + RawSocket = 0x10000, + ReliableDatagramSocket = 0x20000, + // Packet is considered obsolete +}; + +enum { + InternetProtocol = 1, + InternetProtocol6 = 2, + UnixDomain = 3, + LocalDomain = 3, +}; + +enum { + ClientRole, + ServerRole, +}; + +class Socket : public FsNode { +protected: + int type = 0; // Type (Stream, Datagram, etc.) + int domain = 0; // Domain (UNIX, INET, etc.) + Semaphore pendingConnections = Semaphore(CONNECTION_BACKLOG); // Pending Connections semaphore + List pending; // Pending Connections + + bool bound = false; // Has it been bound to an address> + bool passive = false; // Listening? + bool blocking = true; +public: + bool connected = false; // Connected? + int role; // Server/Client + + static Socket* CreateSocket(int domain, int type, int protocol); + + Socket(int type, int protocol); + virtual ~Socket(); + + virtual Socket* Accept(sockaddr* addr, socklen_t* addrlen); + virtual Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); + virtual int Bind(const sockaddr* addr, socklen_t addrlen); + virtual int Connect(const sockaddr* addr, socklen_t addrlen); + virtual int Listen(int backlog); + + virtual int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); + virtual int64_t Receive(void* buffer, size_t len, int flags); + virtual ssize_t Read(size_t offset, size_t size, uint8_t* buffer); + + virtual int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); + virtual int64_t Send(void* buffer, size_t len, int flags); + virtual ssize_t Write(size_t offset, size_t size, uint8_t* buffer); + + virtual fs_fd_t* Open(size_t flags); + virtual void Close(); + + virtual void Watch(FilesystemWatcher& watcher, int events); + virtual void Unwatch(FilesystemWatcher& watcher); + + virtual int GetDomain() { return domain; } + virtual int IsListening() { return passive; } + virtual int IsBlocking() { return blocking; } + virtual int IsConnected() { return connected; } + + virtual int PendingConnections() { return pending.get_length(); } +}; + +class LocalSocket : public Socket { + lock_t slock = 0; + + lock_t watcherLock = 0; + List watching; +public: + LocalSocket* peer = nullptr; + + Stream* inbound = nullptr; + Stream* outbound = nullptr; + + LocalSocket(int type, int protocol); + + int ConnectTo(Socket* client); + void DisconnectPeer(); + + void OnDisconnect(); + + Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); + int Bind(const sockaddr* addr, socklen_t addrlen); + int Connect(const sockaddr* addr, socklen_t addrlen); + int Listen(int backlog); + + fs_fd_t* Open(size_t flags); + void Close(); + + int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); + int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); + + void Watch(FilesystemWatcher& watcher, int events); + void Unwatch(FilesystemWatcher& watcher); + + bool CanRead() { if(inbound) return !inbound->Empty(); else return false; } +}; + +class IPSocket : public Socket { +protected: + IPv4Address address = 0; + BigEndian port = 0; + BigEndian destinationPort = 0; + + List pQueue; + + virtual int64_t IPReceiveFrom(void* buffer, size_t len); +public: + IPSocket(int type, int protocol); + virtual ~IPSocket(); + + Socket* Accept(sockaddr* addr, socklen_t* addrlen, int mode); + int Bind(const sockaddr* addr, socklen_t addrlen); + int Connect(const sockaddr* addr, socklen_t addrlen); + int Listen(int backlog); + + void Close(); + + int64_t ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen); + virtual int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); +}; + +class UDPSocket : public IPSocket { + int64_t IPReceiveFrom(void* buffer, size_t len); +public: + UDPSocket(int type, int protocol); + int64_t SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen); +}; + +namespace SocketManager{ + typedef struct SocketBinding{ + char* address; + Socket* socket; + } sock_binding_t; + + Socket* ResolveSocketAddress(const sockaddr* addr, socklen_t addrlen); + int BindSocket(Socket* sock, const sockaddr* addr, socklen_t addrlen); + void DestroySocket(Socket* sock); } \ No newline at end of file diff --git a/Kernel/linkscript-x86.ld b/Kernel/linkscript-x86.ld index 5f3485b5..a7fb4fad 100755 --- a/Kernel/linkscript-x86.ld +++ b/Kernel/linkscript-x86.ld @@ -1,66 +1,66 @@ -ENTRY(entry) -OUTPUT_FORMAT(elf32-i386) - -KERNEL_VIRTUAL_BASE = 0xC0000000; - -SECTIONS { - . = 100000; - - .multiboot.hdr : { - *(.multiboot.hdr) - } - - .multiboot.data : { - *(.multiboot.data) - } - - .multiboot.text : { - *(.multiboot.text) - } - - . += KERNEL_VIRTUAL_BASE; - - .text ALIGN(4096) : AT(ADDR(.text) - KERNEL_VIRTUAL_BASE) { - *(.text) - } - - .data ALIGN (4096) : AT(ADDR(.data) - KERNEL_VIRTUAL_BASE) { - *(.data) - *(.rodata*) - } - - .bss ALIGN (4096) : AT(ADDR(.bss) - KERNEL_VIRTUAL_BASE) { - _sbss = .; - *(COMMON) - *(.bss) - _ebss = .; - } - - /DISCARD/ : { - *(.eh_frame); - *(.comment*); - } - - kernel_end = .; -} - - -/*SECTIONS -{ - . = 100000; - - .multiboot : { *(.multiboot); } - .text : { *(.text); } - .data : { - *(.data) ; - *(.rodata*); - } - .bss : { *(.bss);} - - /DISCARD/ : { - *(.eh_frame); - *(.comment*); - } - - kernel_end = .; +ENTRY(entry) +OUTPUT_FORMAT(elf32-i386) + +KERNEL_VIRTUAL_BASE = 0xC0000000; + +SECTIONS { + . = 100000; + + .multiboot.hdr : { + *(.multiboot.hdr) + } + + .multiboot.data : { + *(.multiboot.data) + } + + .multiboot.text : { + *(.multiboot.text) + } + + . += KERNEL_VIRTUAL_BASE; + + .text ALIGN(4096) : AT(ADDR(.text) - KERNEL_VIRTUAL_BASE) { + *(.text) + } + + .data ALIGN (4096) : AT(ADDR(.data) - KERNEL_VIRTUAL_BASE) { + *(.data) + *(.rodata*) + } + + .bss ALIGN (4096) : AT(ADDR(.bss) - KERNEL_VIRTUAL_BASE) { + _sbss = .; + *(COMMON) + *(.bss) + _ebss = .; + } + + /DISCARD/ : { + *(.eh_frame); + *(.comment*); + } + + kernel_end = .; +} + + +/*SECTIONS +{ + . = 100000; + + .multiboot : { *(.multiboot); } + .text : { *(.text); } + .data : { + *(.data) ; + *(.rodata*); + } + .bss : { *(.bss);} + + /DISCARD/ : { + *(.eh_frame); + *(.comment*); + } + + kernel_end = .; }*/ \ No newline at end of file diff --git a/Kernel/linkscript-x86_64.ld b/Kernel/linkscript-x86_64.ld index bf727552..79100db1 100755 --- a/Kernel/linkscript-x86_64.ld +++ b/Kernel/linkscript-x86_64.ld @@ -1,69 +1,69 @@ -ENTRY(entry) -SECTIONS -{ - KERNEL_VMA = 0xFFFFFFFF80000000; - . = 0x100000; - - .boot.text : { - *(.boot.text) - } - - .boot.data : - { - *(.boot.data) - . = ALIGN(4096); - } - . += KERNEL_VMA; - - .text : AT(ADDR(.text) - KERNEL_VMA) - { - _code = .; - *(.text) - . = ALIGN(8); - _ctors_start = .; - KEEP(*(.init_array .ctors)) - _ctors_end = .; - . = ALIGN(4096); - } - - .rodata : AT(ADDR(.rodata) - KERNEL_VMA) - { - _rodata = .; - *(.rodata) - . = ALIGN(4096); - } - - .data : AT(ADDR(.data) - KERNEL_VMA) - { - _data = .; - *(.data) - _trampoline = .; - *(.trampoline) - _trampoline_end = .; - . = ALIGN(4096); - } - - .eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) - { - _ehframe = .; - *(.eh_frame) - . = ALIGN(4096); - } - - .bss : AT(ADDR(.bss) - KERNEL_VMA) - { - _bss = .; - *(.bss) - - *(COMMON) - . = ALIGN(4096); - _bss_end = .; - } - - _end = .; - - /DISCARD/ : - { - *(.comment) - } -} +ENTRY(entry) +SECTIONS +{ + KERNEL_VMA = 0xFFFFFFFF80000000; + . = 0x100000; + + .boot.text : { + *(.boot.text) + } + + .boot.data : + { + *(.boot.data) + . = ALIGN(4096); + } + . += KERNEL_VMA; + + .text : AT(ADDR(.text) - KERNEL_VMA) + { + _code = .; + *(.text) + . = ALIGN(8); + _ctors_start = .; + KEEP(*(.init_array .ctors)) + _ctors_end = .; + . = ALIGN(4096); + } + + .rodata : AT(ADDR(.rodata) - KERNEL_VMA) + { + _rodata = .; + *(.rodata) + . = ALIGN(4096); + } + + .data : AT(ADDR(.data) - KERNEL_VMA) + { + _data = .; + *(.data) + _trampoline = .; + *(.trampoline) + _trampoline_end = .; + . = ALIGN(4096); + } + + .eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) + { + _ehframe = .; + *(.eh_frame) + . = ALIGN(4096); + } + + .bss : AT(ADDR(.bss) - KERNEL_VMA) + { + _bss = .; + *(.bss) + + *(COMMON) + . = ALIGN(4096); + _bss_end = .; + } + + _end = .; + + /DISCARD/ : + { + *(.comment) + } +} diff --git a/Kernel/meson.build b/Kernel/meson.build index c5cbc93d..eeb98f02 100755 --- a/Kernel/meson.build +++ b/Kernel/meson.build @@ -1,148 +1,148 @@ -project('Lemon Kernel', - default_options : ['warning_level=2', 'cpp_std=c++2a', 'optimization=0', 'werror=true']) -add_languages('c', 'cpp') - -nasm = find_program('nasm') -asmg = generator(nasm, - output : '@BASENAME@.asm.o', - arguments : [ - '-f', 'elf64', - '-g', '-F', 'dwarf', '-w+gnu-elf-extensions', - '-i', meson.current_source_dir() + '/src/arch/x86_64/', - '@INPUT@', - '-o', '@OUTPUT@']) - - -bintoelf = find_program('bintoelf.sh', './bintoelf.sh') -bing = generator(bintoelf, -output : '@BASENAME@.bin.o', -arguments : ['@INPUT@','@OUTPUT@', meson.current_source_dir() + '/src/arch/x86_64/', '@BASENAME@']) - -kernel_c_args = [ - '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-sign-compare', - '-DLemon64', - '-ffreestanding', '-nostdlib', - '-mcmodel=large', '-mno-red-zone', '-fno-pic', - '-mno-mmx', '-mno-sse', '-mno-sse2', - '-fno-stack-protector', '-fno-builtin', -] - -kernel_cpp_args = [ - '-fno-exceptions', '-fno-rtti', '-Wno-deprecated-volatile', '-Wno-non-c-typedef-for-linkage', -] - -add_project_arguments(kernel_c_args, language : 'c') -add_project_arguments(kernel_c_args, language : 'cpp') -add_project_arguments(kernel_cpp_args, language : 'cpp') - -lai = subproject('lai') - -kernel_include_dirs = [ - include_directories('include'), - include_directories('subprojects/lai/include'), - include_directories('include/arch/x86_64'), -] - -cpp_files = [ - 'src/kernel.cpp', - 'src/characterbuffer.cpp', - 'src/device.cpp', - 'src/gpt.cpp', - 'src/lemon.cpp', - 'src/logging.cpp', - 'src/math.cpp', - 'src/panic.cpp', - 'src/runtime.cpp', - 'src/string.cpp', - 'src/video.cpp', - 'src/videoconsole.cpp', - 'src/sharedmem.cpp', - 'src/assert.cpp', - 'src/streams.cpp', - 'src/lock.cpp', - 'src/debug.cpp', - - 'src/fs/fat32.cpp', - 'src/fs/ext2.cpp', - 'src/fs/filesystem.cpp', - 'src/fs/fsvolume.cpp', - 'src/fs/tar.cpp', - 'src/fs/fsnodestubs.cpp', - - 'src/liballoc/_liballoc.cpp', - 'src/liballoc/liballoc.c', - - 'src/net/networkadapter.cpp', - 'src/net/8254x.cpp', - 'src/net/socket.cpp', - 'src/net/net.cpp', - 'src/net/interface.cpp', - 'src/net/ipsocket.cpp', - - 'src/objects/kobject.cpp', - 'src/objects/message.cpp', - 'src/objects/interface.cpp', - 'src/objects/service.cpp', - - 'src/storage/ahci.cpp', - 'src/storage/ahciport.cpp', - 'src/storage/ata.cpp', - 'src/storage/atadrive.cpp', - 'src/storage/diskdevice.cpp', - 'src/storage/nvme.cpp', - 'src/storage/nvmenamespace.cpp', - 'src/storage/partitiondevice.cpp', - - 'src/tty/pty.cpp', - - 'src/usb/xhci.cpp', -] - -cpp_files_x86_64 = [ - 'src/arch/x86_64/acpi.cpp', - 'src/arch/x86_64/apic.cpp', - 'src/arch/x86_64/cpuid.cpp', - 'src/arch/x86_64/hal.cpp', - 'src/arch/x86_64/idt.cpp', - 'src/arch/x86_64/keyboard.cpp', - 'src/arch/x86_64/mouse.cpp', - 'src/arch/x86_64/paging.cpp', - 'src/arch/x86_64/pci.cpp', - 'src/arch/x86_64/physicalallocator.cpp', - 'src/arch/x86_64/scheduler.cpp', - 'src/arch/x86_64/serial.cpp', - 'src/arch/x86_64/smp.cpp', - 'src/arch/x86_64/ssp.cpp', - 'src/arch/x86_64/stringsafe.cpp', - 'src/arch/x86_64/syscalls.cpp', - 'src/arch/x86_64/system.cpp', - 'src/arch/x86_64/timer.cpp', - 'src/arch/x86_64/tss.cpp', - 'src/arch/x86_64/elf.cpp', -] - -asm_files_x86_64 = [ - 'src/arch/x86_64/entry.asm', - 'src/arch/x86_64/idt.asm', - 'src/arch/x86_64/scheduler.asm', - 'src/arch/x86_64/sse2.asm', - 'src/arch/x86_64/tss.asm', - 'src/arch/x86_64/lock.asm', -] - -asm_bin_files_x86_64 = [ - 'src/arch/x86_64/smptrampoline.asm', -] - -kernel_link_args = [ - '-m64', - '-T', meson.current_source_dir() + '/linkscript-x86_64.ld', - '-z', 'max-page-size=0x1000', -] - -kernel_link_args += kernel_c_args - -executable('kernel.sys', - [asmg.process(asm_files_x86_64), bing.process(asm_bin_files_x86_64), cpp_files, cpp_files_x86_64, lai.get_variable('sources')], - include_directories : [kernel_include_dirs], - c_args : kernel_c_args, cpp_args : kernel_cpp_args, link_args: kernel_link_args, link_depends: 'linkscript-x86_64.ld') +project('Lemon Kernel', + default_options : ['warning_level=2', 'cpp_std=c++2a', 'optimization=0', 'werror=true']) +add_languages('c', 'cpp') + +nasm = find_program('nasm') +asmg = generator(nasm, + output : '@BASENAME@.asm.o', + arguments : [ + '-f', 'elf64', + '-g', '-F', 'dwarf', '-w+gnu-elf-extensions', + '-i', meson.current_source_dir() + '/src/arch/x86_64/', + '@INPUT@', + '-o', '@OUTPUT@']) + + +bintoelf = find_program('bintoelf.sh', './bintoelf.sh') +bing = generator(bintoelf, +output : '@BASENAME@.bin.o', +arguments : ['@INPUT@','@OUTPUT@', meson.current_source_dir() + '/src/arch/x86_64/', '@BASENAME@']) + +kernel_c_args = [ + '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-sign-compare', + '-DLemon64', + '-ffreestanding', '-nostdlib', + '-mcmodel=large', '-mno-red-zone', '-fno-pic', + '-mno-mmx', '-mno-sse', '-mno-sse2', + '-fno-stack-protector', '-fno-builtin', +] + +kernel_cpp_args = [ + '-fno-exceptions', '-fno-rtti', '-Wno-deprecated-volatile', '-Wno-non-c-typedef-for-linkage', +] + +add_project_arguments(kernel_c_args, language : 'c') +add_project_arguments(kernel_c_args, language : 'cpp') +add_project_arguments(kernel_cpp_args, language : 'cpp') + +lai = subproject('lai') + +kernel_include_dirs = [ + include_directories('include'), + include_directories('subprojects/lai/include'), + include_directories('include/arch/x86_64'), +] + +cpp_files = [ + 'src/kernel.cpp', + 'src/characterbuffer.cpp', + 'src/device.cpp', + 'src/gpt.cpp', + 'src/lemon.cpp', + 'src/logging.cpp', + 'src/math.cpp', + 'src/panic.cpp', + 'src/runtime.cpp', + 'src/string.cpp', + 'src/video.cpp', + 'src/videoconsole.cpp', + 'src/sharedmem.cpp', + 'src/assert.cpp', + 'src/streams.cpp', + 'src/lock.cpp', + 'src/debug.cpp', + + 'src/fs/fat32.cpp', + 'src/fs/ext2.cpp', + 'src/fs/filesystem.cpp', + 'src/fs/fsvolume.cpp', + 'src/fs/tar.cpp', + 'src/fs/fsnodestubs.cpp', + + 'src/liballoc/_liballoc.cpp', + 'src/liballoc/liballoc.c', + + 'src/net/networkadapter.cpp', + 'src/net/8254x.cpp', + 'src/net/socket.cpp', + 'src/net/net.cpp', + 'src/net/interface.cpp', + 'src/net/ipsocket.cpp', + + 'src/objects/kobject.cpp', + 'src/objects/message.cpp', + 'src/objects/interface.cpp', + 'src/objects/service.cpp', + + 'src/storage/ahci.cpp', + 'src/storage/ahciport.cpp', + 'src/storage/ata.cpp', + 'src/storage/atadrive.cpp', + 'src/storage/diskdevice.cpp', + 'src/storage/nvme.cpp', + 'src/storage/nvmenamespace.cpp', + 'src/storage/partitiondevice.cpp', + + 'src/tty/pty.cpp', + + 'src/usb/xhci.cpp', +] + +cpp_files_x86_64 = [ + 'src/arch/x86_64/acpi.cpp', + 'src/arch/x86_64/apic.cpp', + 'src/arch/x86_64/cpuid.cpp', + 'src/arch/x86_64/hal.cpp', + 'src/arch/x86_64/idt.cpp', + 'src/arch/x86_64/keyboard.cpp', + 'src/arch/x86_64/mouse.cpp', + 'src/arch/x86_64/paging.cpp', + 'src/arch/x86_64/pci.cpp', + 'src/arch/x86_64/physicalallocator.cpp', + 'src/arch/x86_64/scheduler.cpp', + 'src/arch/x86_64/serial.cpp', + 'src/arch/x86_64/smp.cpp', + 'src/arch/x86_64/ssp.cpp', + 'src/arch/x86_64/stringsafe.cpp', + 'src/arch/x86_64/syscalls.cpp', + 'src/arch/x86_64/system.cpp', + 'src/arch/x86_64/timer.cpp', + 'src/arch/x86_64/tss.cpp', + 'src/arch/x86_64/elf.cpp', +] + +asm_files_x86_64 = [ + 'src/arch/x86_64/entry.asm', + 'src/arch/x86_64/idt.asm', + 'src/arch/x86_64/scheduler.asm', + 'src/arch/x86_64/sse2.asm', + 'src/arch/x86_64/tss.asm', + 'src/arch/x86_64/lock.asm', +] + +asm_bin_files_x86_64 = [ + 'src/arch/x86_64/smptrampoline.asm', +] + +kernel_link_args = [ + '-m64', + '-T', meson.current_source_dir() + '/linkscript-x86_64.ld', + '-z', 'max-page-size=0x1000', +] + +kernel_link_args += kernel_c_args + +executable('kernel.sys', + [asmg.process(asm_files_x86_64), bing.process(asm_bin_files_x86_64), cpp_files, cpp_files_x86_64, lai.get_variable('sources')], + include_directories : [kernel_include_dirs], + c_args : kernel_c_args, cpp_args : kernel_cpp_args, link_args: kernel_link_args, link_depends: 'linkscript-x86_64.ld') diff --git a/Kernel/src/arch/x86_64/hal.cpp b/Kernel/src/arch/x86_64/hal.cpp index 79eb7f31..5819aa86 100755 --- a/Kernel/src/arch/x86_64/hal.cpp +++ b/Kernel/src/arch/x86_64/hal.cpp @@ -1,223 +1,223 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -extern void* _end; - -namespace HAL{ - memory_info_t mem_info; - video_mode_t videoMode; - multiboot2_info_header_t* multibootInfo; - uintptr_t multibootModulesAddress; - boot_module_t bootModules[128]; - int bootModuleCount; - bool debugMode = false; - bool disableSMP = false; - bool useKCon = false; - VideoConsole* con; - - void InitCore(multiboot2_info_header_t* mbInfo){ // ALWAYS call this first - // Check if Debugging Mode is enabled and if so initialize serial port - initialize_serial(); - Log::Info("Initializing Lemon...\r\n"); - - // Initialize IDT - IDT::Initialize(); - - // Initialize Paging/Virtual Memory Manager - Memory::InitializeVirtualMemory(); - - //multibootModulesAddress = Memory::GetIOMapping(multibootInfo.modsAddr); // Grub loads the kernel as 32-bit so modules will be <4GB - - char* cmdLine = nullptr; - - asm("cli"); - - // Initialize Physical Memory Allocator - Memory::InitializePhysicalAllocator(&mem_info); - - multiboot2_tag_t* tag = reinterpret_cast(mbInfo->tags); - - multiboot2_module_t* modules[128]; - unsigned bootModuleCount = 0; - - while(tag->type && reinterpret_cast(tag) < reinterpret_cast(mbInfo) + mbInfo->totalSize){ - switch(tag->type){ - case Mboot2CmdLine: { - multiboot2_cmdline_t* mbCmdLine = reinterpret_cast(tag); - - cmdLine = mbCmdLine->string; - break; - } - case Mboot2Modules:{ - if(bootModuleCount >= 128){ - Log::Warning("Exceeded maximum amount of boot modules!"); - break; - } - - multiboot2_module_t* mod = reinterpret_cast(tag); - - modules[bootModuleCount++] = mod; - break; - } - case Mboot2MemoryInfo: { - multiboot2_memory_info_t* mbMemInfo = reinterpret_cast(tag); - Log::Info("Bootloader reports %d MB of memory", (mbMemInfo->memoryLower + mbMemInfo->memoryUpper) / 1024); - break; - } - case Mboot2MemoryMap: { - multiboot2_memory_map_t* mbMemMap = reinterpret_cast(tag); - - multiboot2_mmap_entry_t* currentEntry = mbMemMap->entries; - - mem_info.totalMemory = 0; - while(reinterpret_cast(currentEntry) < reinterpret_cast(mbMemMap) + mbMemMap->size){ - switch (currentEntry->type) - { - case 1: // Available - if(debugLevelHAL >= DebugLevelVerbose){ - Log::Info("Memory region [%x-%x] available", currentEntry->base, currentEntry->base + currentEntry->length); - } - Memory::MarkMemoryRegionFree(currentEntry->base, currentEntry->length); - mem_info.totalMemory += currentEntry->length; - break; - default: // Not available - if(debugLevelHAL >= DebugLevelVerbose){ - Log::Info("Memory region [%x-%x] reserved", currentEntry->base, currentEntry->base + currentEntry->length); - } - break; - } - currentEntry = reinterpret_cast((uintptr_t)currentEntry + mbMemMap->entrySize); - } - Memory::usedPhysicalBlocks = 0; - break; - } - case Mboot2FramebufferInfo: { - multiboot2_framebuffer_info_t* mbFbInfo = reinterpret_cast(tag); - - videoMode.address = reinterpret_cast(Memory::KernelAllocate4KPages((mbFbInfo->framebufferPitch * mbFbInfo->framebufferHeight + (PAGE_SIZE_4K - 1)) / PAGE_SIZE_4K)); - Memory::KernelMapVirtualMemory4K(mbFbInfo->framebufferAddr, (uintptr_t)videoMode.address, ((mbFbInfo->framebufferPitch * mbFbInfo->framebufferHeight + (PAGE_SIZE_4K - 1)) / PAGE_SIZE_4K), PAGE_PAT_WRITE_COMBINING | PAGE_WRITABLE | PAGE_PRESENT); - - videoMode.width = mbFbInfo->framebufferWidth; - videoMode.height = mbFbInfo->framebufferHeight; - videoMode.pitch = mbFbInfo->framebufferPitch; - videoMode.bpp = mbFbInfo->framebufferBpp; - - videoMode.physicalAddress = mbFbInfo->framebufferAddr; - - videoMode.type = mbFbInfo->type; - break; - } - case Mboot2ACPI1RSDP: { - auto rsdp = &(reinterpret_cast(tag)->rsdp); - ACPI::SetRSDP(rsdp); - break; - } - case Mboot2ACPI2RSDP: { - auto rsdp = &(reinterpret_cast(tag)->rsdp); - ACPI::SetRSDP(rsdp); - break; - } - default: { - if(debugLevelHAL >= DebugLevelVerbose){ - Log::Info("Ignoring boot tag %d", tag->type); - } - break; - } - } - - tag = tag->next(); // Get next tag - } - - Memory::MarkMemoryRegionUsed(0, (uintptr_t)&_end - KERNEL_VIRTUAL_BASE); // Make sure kernel memory is marked as used - - if(cmdLine){ - cmdLine = strtok((char*)cmdLine, " "); - - while(cmdLine){ - if(strcmp(cmdLine, "debug") == 0) debugMode = true; - else if(strcmp(cmdLine, "nosmp") == 0) disableSMP = true; - else if(strcmp(cmdLine, "kcon") == 0) useKCon = true; - cmdLine = strtok(NULL, " "); - } - } - - asm("sti"); - Log::Initialize(); - - // Manage Multiboot Modules - if(debugLevelHAL >= DebugLevelNormal) - Log::Info("Multiboot Module Count: %d", bootModuleCount); - - for(unsigned i = 0; i < bootModuleCount; i++){ - multiboot2_module_t& mod = *modules[i]; - - if(debugLevelHAL >= DebugLevelNormal){ - Log::Info(" Multiboot Module %d [Start: %x, End: %x, Cmdline: %s]", i, mod.moduleStart, mod.moduleEnd, mod.string); - } - - Memory::MarkMemoryRegionUsed(mod.moduleStart, mod.moduleEnd - mod.moduleStart); - bootModules[i] = { - .base = Memory::GetIOMapping(mod.moduleStart), - .size = mod.moduleEnd - mod.moduleStart, - }; - - } - - Log::Info("Initializing System Timer..."); - Timer::Initialize(1000); - Log::Write("OK"); - } - - void InitVideo(){ - Video::Initialize(videoMode); - Video::DrawString("Starting Lemon x64...", 0, 0, 255, 255, 255); - - Log::SetVideoConsole(NULL); - - if(debugMode){ - con = new VideoConsole(0, (videoMode.height / 3) * 2, videoMode.width, videoMode.height / 3); - Log::SetVideoConsole(con); - } - } - - void InitExtra(){ - Log::Info("Initializing ACPI..."); - ACPI::Init(); - Log::Write("OK"); - - Log::Info("Initializing PCI..."); - PCI::Init(); - Log::Write("OK"); - - Log::Info("Initializing Local and I/O APIC..."); - APIC::Initialize(); - Log::Write("OK"); - - Log::Info("Initializing SMP..."); - SMP::Initialize(); - Log::Write("OK"); - } - - void Init(multiboot2_info_header_t* mb_info){ - InitCore(mb_info); - InitVideo(); - InitExtra(); - } -} +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern void* _end; + +namespace HAL{ + memory_info_t mem_info; + video_mode_t videoMode; + multiboot2_info_header_t* multibootInfo; + uintptr_t multibootModulesAddress; + boot_module_t bootModules[128]; + int bootModuleCount; + bool debugMode = false; + bool disableSMP = false; + bool useKCon = false; + VideoConsole* con; + + void InitCore(multiboot2_info_header_t* mbInfo){ // ALWAYS call this first + // Check if Debugging Mode is enabled and if so initialize serial port + initialize_serial(); + Log::Info("Initializing Lemon...\r\n"); + + // Initialize IDT + IDT::Initialize(); + + // Initialize Paging/Virtual Memory Manager + Memory::InitializeVirtualMemory(); + + //multibootModulesAddress = Memory::GetIOMapping(multibootInfo.modsAddr); // Grub loads the kernel as 32-bit so modules will be <4GB + + char* cmdLine = nullptr; + + asm("cli"); + + // Initialize Physical Memory Allocator + Memory::InitializePhysicalAllocator(&mem_info); + + multiboot2_tag_t* tag = reinterpret_cast(mbInfo->tags); + + multiboot2_module_t* modules[128]; + unsigned bootModuleCount = 0; + + while(tag->type && reinterpret_cast(tag) < reinterpret_cast(mbInfo) + mbInfo->totalSize){ + switch(tag->type){ + case Mboot2CmdLine: { + multiboot2_cmdline_t* mbCmdLine = reinterpret_cast(tag); + + cmdLine = mbCmdLine->string; + break; + } + case Mboot2Modules:{ + if(bootModuleCount >= 128){ + Log::Warning("Exceeded maximum amount of boot modules!"); + break; + } + + multiboot2_module_t* mod = reinterpret_cast(tag); + + modules[bootModuleCount++] = mod; + break; + } + case Mboot2MemoryInfo: { + multiboot2_memory_info_t* mbMemInfo = reinterpret_cast(tag); + Log::Info("Bootloader reports %d MB of memory", (mbMemInfo->memoryLower + mbMemInfo->memoryUpper) / 1024); + break; + } + case Mboot2MemoryMap: { + multiboot2_memory_map_t* mbMemMap = reinterpret_cast(tag); + + multiboot2_mmap_entry_t* currentEntry = mbMemMap->entries; + + mem_info.totalMemory = 0; + while(reinterpret_cast(currentEntry) < reinterpret_cast(mbMemMap) + mbMemMap->size){ + switch (currentEntry->type) + { + case 1: // Available + if(debugLevelHAL >= DebugLevelVerbose){ + Log::Info("Memory region [%x-%x] available", currentEntry->base, currentEntry->base + currentEntry->length); + } + Memory::MarkMemoryRegionFree(currentEntry->base, currentEntry->length); + mem_info.totalMemory += currentEntry->length; + break; + default: // Not available + if(debugLevelHAL >= DebugLevelVerbose){ + Log::Info("Memory region [%x-%x] reserved", currentEntry->base, currentEntry->base + currentEntry->length); + } + break; + } + currentEntry = reinterpret_cast((uintptr_t)currentEntry + mbMemMap->entrySize); + } + Memory::usedPhysicalBlocks = 0; + break; + } + case Mboot2FramebufferInfo: { + multiboot2_framebuffer_info_t* mbFbInfo = reinterpret_cast(tag); + + videoMode.address = reinterpret_cast(Memory::KernelAllocate4KPages((mbFbInfo->framebufferPitch * mbFbInfo->framebufferHeight + (PAGE_SIZE_4K - 1)) / PAGE_SIZE_4K)); + Memory::KernelMapVirtualMemory4K(mbFbInfo->framebufferAddr, (uintptr_t)videoMode.address, ((mbFbInfo->framebufferPitch * mbFbInfo->framebufferHeight + (PAGE_SIZE_4K - 1)) / PAGE_SIZE_4K), PAGE_PAT_WRITE_COMBINING | PAGE_WRITABLE | PAGE_PRESENT); + + videoMode.width = mbFbInfo->framebufferWidth; + videoMode.height = mbFbInfo->framebufferHeight; + videoMode.pitch = mbFbInfo->framebufferPitch; + videoMode.bpp = mbFbInfo->framebufferBpp; + + videoMode.physicalAddress = mbFbInfo->framebufferAddr; + + videoMode.type = mbFbInfo->type; + break; + } + case Mboot2ACPI1RSDP: { + auto rsdp = &(reinterpret_cast(tag)->rsdp); + ACPI::SetRSDP(rsdp); + break; + } + case Mboot2ACPI2RSDP: { + auto rsdp = &(reinterpret_cast(tag)->rsdp); + ACPI::SetRSDP(rsdp); + break; + } + default: { + if(debugLevelHAL >= DebugLevelVerbose){ + Log::Info("Ignoring boot tag %d", tag->type); + } + break; + } + } + + tag = tag->next(); // Get next tag + } + + Memory::MarkMemoryRegionUsed(0, (uintptr_t)&_end - KERNEL_VIRTUAL_BASE); // Make sure kernel memory is marked as used + + if(cmdLine){ + cmdLine = strtok((char*)cmdLine, " "); + + while(cmdLine){ + if(strcmp(cmdLine, "debug") == 0) debugMode = true; + else if(strcmp(cmdLine, "nosmp") == 0) disableSMP = true; + else if(strcmp(cmdLine, "kcon") == 0) useKCon = true; + cmdLine = strtok(NULL, " "); + } + } + + asm("sti"); + Log::Initialize(); + + // Manage Multiboot Modules + if(debugLevelHAL >= DebugLevelNormal) + Log::Info("Multiboot Module Count: %d", bootModuleCount); + + for(unsigned i = 0; i < bootModuleCount; i++){ + multiboot2_module_t& mod = *modules[i]; + + if(debugLevelHAL >= DebugLevelNormal){ + Log::Info(" Multiboot Module %d [Start: %x, End: %x, Cmdline: %s]", i, mod.moduleStart, mod.moduleEnd, mod.string); + } + + Memory::MarkMemoryRegionUsed(mod.moduleStart, mod.moduleEnd - mod.moduleStart); + bootModules[i] = { + .base = Memory::GetIOMapping(mod.moduleStart), + .size = mod.moduleEnd - mod.moduleStart, + }; + + } + + Log::Info("Initializing System Timer..."); + Timer::Initialize(1000); + Log::Write("OK"); + } + + void InitVideo(){ + Video::Initialize(videoMode); + Video::DrawString("Starting Lemon x64...", 0, 0, 255, 255, 255); + + Log::SetVideoConsole(NULL); + + if(debugMode){ + con = new VideoConsole(0, (videoMode.height / 3) * 2, videoMode.width, videoMode.height / 3); + Log::SetVideoConsole(con); + } + } + + void InitExtra(){ + Log::Info("Initializing ACPI..."); + ACPI::Init(); + Log::Write("OK"); + + Log::Info("Initializing PCI..."); + PCI::Init(); + Log::Write("OK"); + + Log::Info("Initializing Local and I/O APIC..."); + APIC::Initialize(); + Log::Write("OK"); + + Log::Info("Initializing SMP..."); + SMP::Initialize(); + Log::Write("OK"); + } + + void Init(multiboot2_info_header_t* mb_info){ + InitCore(mb_info); + InitVideo(); + InitExtra(); + } +} diff --git a/Kernel/src/arch/x86_64/idt.asm b/Kernel/src/arch/x86_64/idt.asm index ddac796f..22dc483b 100755 --- a/Kernel/src/arch/x86_64/idt.asm +++ b/Kernel/src/arch/x86_64/idt.asm @@ -1,190 +1,190 @@ -BITS 64 - -extern isr_handler -extern irq_handler -extern ipi_handler -extern LocalAPICEOI - -global idt_flush -global int_vectors - -extern idt_ptr - -section .text -%macro pushaq 0 - push rax - push rbx - push rcx - push rdx - push rsi - push rdi - push rbp - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r14 - push r15 -%endmacro - -%macro popaq 0 - pop r15 - pop r14 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - pop rbp - pop rdi - pop rsi - pop rdx - pop rcx - pop rbx - pop rax -%endmacro - -idt_flush: - lidt[idt_ptr] - ret - iretq - -%macro ISR_ERROR_CODE 1 - global isr%1 - isr%1: - cli - push qword [rsp+5*8] ; SS - push qword [rsp+5*8] ; RSP - push qword [rsp+5*8] ; RFLAGS - push qword [rsp+5*8] ; CS - push qword [rsp+5*8] ; RIP - pushaq - mov rdi, %1 - mov rsi, rsp - mov rdx, qword [rsp+20*8] - xor rbp, rbp - call isr_handler - popaq - iretq -%endmacro - -%macro ISR_NO_ERROR_CODE 1 - global isr%1 - isr%1: - cli - pushaq - mov rdi, %1 - mov rsi, rsp - xor rdx, rdx - xor rbp, rbp - call isr_handler - popaq - iretq -%endmacro - -%macro IPI 1 - global ipi%1 - ipi%1: - cli - pushaq - mov rdi, %1 - mov rsi, rsp - xor rdx, rdx - xor rbp, rbp - call ipi_handler - popaq - iretq -%endmacro - -%macro IRQ 2 - global irq%1 - irq%1: - cli - pushaq - mov rdi, %2 - mov rsi, rsp - xor rdx, rdx - xor rbp, rbp - call irq_handler - popaq - iretq -%endmacro - -ISR_NO_ERROR_CODE 0 -ISR_NO_ERROR_CODE 1 -ISR_NO_ERROR_CODE 2 -ISR_NO_ERROR_CODE 3 -ISR_NO_ERROR_CODE 4 -ISR_NO_ERROR_CODE 5 -ISR_NO_ERROR_CODE 6 -ISR_NO_ERROR_CODE 7 -ISR_ERROR_CODE 8 -ISR_NO_ERROR_CODE 9 -ISR_ERROR_CODE 10 -ISR_ERROR_CODE 11 -ISR_ERROR_CODE 12 -ISR_ERROR_CODE 13 -ISR_ERROR_CODE 14 -ISR_NO_ERROR_CODE 15 -ISR_NO_ERROR_CODE 16 -ISR_ERROR_CODE 17 -ISR_NO_ERROR_CODE 18 -ISR_NO_ERROR_CODE 19 -ISR_NO_ERROR_CODE 20 -ISR_NO_ERROR_CODE 21 -ISR_NO_ERROR_CODE 22 -ISR_NO_ERROR_CODE 23 -ISR_NO_ERROR_CODE 24 -ISR_NO_ERROR_CODE 25 -ISR_NO_ERROR_CODE 26 -ISR_NO_ERROR_CODE 27 -ISR_NO_ERROR_CODE 28 -ISR_NO_ERROR_CODE 29 -ISR_ERROR_CODE 30 -ISR_NO_ERROR_CODE 31 -ISR_NO_ERROR_CODE 32 - -extern SyscallHandler ; Syscall -global isr0x69 -isr0x69: - cli - pushaq - mov rdi, rsp - xor rbp, rbp - call SyscallHandler - popaq - iretq - -%assign num 48 -%rep 256-48 - IPI num -%assign num (num + 1) -%endrep - -IRQ 0, 32 -IRQ 1, 33 -IRQ 2, 34 -IRQ 3, 35 -IRQ 4, 36 -IRQ 5, 37 -IRQ 6, 38 -IRQ 7, 39 -IRQ 8, 40 -IRQ 9, 41 -IRQ 10, 42 -IRQ 11, 43 -IRQ 12, 44 -IRQ 13, 45 -IRQ 14, 46 -IRQ 15, 47 - -section .rodata -int_vectors: -%assign num 48 -%rep 256-48 - dq ipi%+ num -%assign num (num + 1) +BITS 64 + +extern isr_handler +extern irq_handler +extern ipi_handler +extern LocalAPICEOI + +global idt_flush +global int_vectors + +extern idt_ptr + +section .text +%macro pushaq 0 + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +%endmacro + +%macro popaq 0 + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax +%endmacro + +idt_flush: + lidt[idt_ptr] + ret + iretq + +%macro ISR_ERROR_CODE 1 + global isr%1 + isr%1: + cli + push qword [rsp+5*8] ; SS + push qword [rsp+5*8] ; RSP + push qword [rsp+5*8] ; RFLAGS + push qword [rsp+5*8] ; CS + push qword [rsp+5*8] ; RIP + pushaq + mov rdi, %1 + mov rsi, rsp + mov rdx, qword [rsp+20*8] + xor rbp, rbp + call isr_handler + popaq + iretq +%endmacro + +%macro ISR_NO_ERROR_CODE 1 + global isr%1 + isr%1: + cli + pushaq + mov rdi, %1 + mov rsi, rsp + xor rdx, rdx + xor rbp, rbp + call isr_handler + popaq + iretq +%endmacro + +%macro IPI 1 + global ipi%1 + ipi%1: + cli + pushaq + mov rdi, %1 + mov rsi, rsp + xor rdx, rdx + xor rbp, rbp + call ipi_handler + popaq + iretq +%endmacro + +%macro IRQ 2 + global irq%1 + irq%1: + cli + pushaq + mov rdi, %2 + mov rsi, rsp + xor rdx, rdx + xor rbp, rbp + call irq_handler + popaq + iretq +%endmacro + +ISR_NO_ERROR_CODE 0 +ISR_NO_ERROR_CODE 1 +ISR_NO_ERROR_CODE 2 +ISR_NO_ERROR_CODE 3 +ISR_NO_ERROR_CODE 4 +ISR_NO_ERROR_CODE 5 +ISR_NO_ERROR_CODE 6 +ISR_NO_ERROR_CODE 7 +ISR_ERROR_CODE 8 +ISR_NO_ERROR_CODE 9 +ISR_ERROR_CODE 10 +ISR_ERROR_CODE 11 +ISR_ERROR_CODE 12 +ISR_ERROR_CODE 13 +ISR_ERROR_CODE 14 +ISR_NO_ERROR_CODE 15 +ISR_NO_ERROR_CODE 16 +ISR_ERROR_CODE 17 +ISR_NO_ERROR_CODE 18 +ISR_NO_ERROR_CODE 19 +ISR_NO_ERROR_CODE 20 +ISR_NO_ERROR_CODE 21 +ISR_NO_ERROR_CODE 22 +ISR_NO_ERROR_CODE 23 +ISR_NO_ERROR_CODE 24 +ISR_NO_ERROR_CODE 25 +ISR_NO_ERROR_CODE 26 +ISR_NO_ERROR_CODE 27 +ISR_NO_ERROR_CODE 28 +ISR_NO_ERROR_CODE 29 +ISR_ERROR_CODE 30 +ISR_NO_ERROR_CODE 31 +ISR_NO_ERROR_CODE 32 + +extern SyscallHandler ; Syscall +global isr0x69 +isr0x69: + cli + pushaq + mov rdi, rsp + xor rbp, rbp + call SyscallHandler + popaq + iretq + +%assign num 48 +%rep 256-48 + IPI num +%assign num (num + 1) +%endrep + +IRQ 0, 32 +IRQ 1, 33 +IRQ 2, 34 +IRQ 3, 35 +IRQ 4, 36 +IRQ 5, 37 +IRQ 6, 38 +IRQ 7, 39 +IRQ 8, 40 +IRQ 9, 41 +IRQ 10, 42 +IRQ 11, 43 +IRQ 12, 44 +IRQ 13, 45 +IRQ 14, 46 +IRQ 15, 47 + +section .rodata +int_vectors: +%assign num 48 +%rep 256-48 + dq ipi%+ num +%assign num (num + 1) %endrep \ No newline at end of file diff --git a/Kernel/src/arch/x86_64/idt.cpp b/Kernel/src/arch/x86_64/idt.cpp index e219de0c..14d30684 100755 --- a/Kernel/src/arch/x86_64/idt.cpp +++ b/Kernel/src/arch/x86_64/idt.cpp @@ -1,347 +1,347 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -idt_entry_t idt[256]; - -idt_ptr_t idt_ptr; - -struct ISRDataPair -{ - isr_t handler; - void* data; -}; -ISRDataPair interrupt_handlers[256]; - -extern "C" -void isr0(); -extern "C" -void isr1(); -extern "C" -void isr2(); -extern "C" -void isr3(); -extern "C" -void isr4(); -extern "C" -void isr5(); -extern "C" -void isr6(); -extern "C" -void isr7(); -extern "C" -void isr8(); -extern "C" -void isr9(); -extern "C" -void isr10(); -extern "C" -void isr11(); -extern "C" -void isr12(); -extern "C" -void isr13(); -extern "C" -void isr14(); -extern "C" -void isr15(); -extern "C" -void isr16(); -extern "C" -void isr17(); -extern "C" -void isr18(); -extern "C" -void isr19(); -extern "C" -void isr20(); -extern "C" -void isr21(); -extern "C" -void isr22(); -extern "C" -void isr23(); -extern "C" -void isr24(); -extern "C" -void isr25(); -extern "C" -void isr26(); -extern "C" -void isr27(); -extern "C" -void isr28(); -extern "C" -void isr29(); -extern "C" -void isr30(); -extern "C" -void isr31(); - -extern "C" -void irq0(); -extern "C" -void irq1(); -extern "C" -void irq2(); -extern "C" -void irq3(); -extern "C" -void irq4(); -extern "C" -void irq5(); -extern "C" -void irq6(); -extern "C" -void irq7(); -extern "C" -void irq8(); -extern "C" -void irq9(); -extern "C" -void irq10(); -extern "C" -void irq11(); -extern "C" -void irq12(); -extern "C" -void irq13(); -extern "C" -void irq14(); -extern "C" -void irq15(); - -extern "C" -void isr0x69(); - -extern "C" -void idt_flush(); - -extern uint64_t int_vectors[]; - -int errCode = 0; - -namespace IDT{ - void IPIHalt(void*, regs64_t* r){ - asm("cli"); - asm("hlt"); - } - - void InvalidInterruptHandler(void*, regs64_t* r){ - Log::Warning("Invalid interrupt handler called!"); - } - - static void SetGate(uint8_t num, uint64_t base, uint16_t sel, uint8_t flags, uint8_t ist = 0) { - idt[num].base_high = (base >> 32); - idt[num].base_med = (base >> 16) & 0xFFFF; - idt[num].base_low = base & 0xFFFF; - - idt[num].sel = sel; - idt[num].null = 0; - idt[num].ist = ist & 0x7; // Interrupt Stack Table (IST) - - idt[num].flags = flags; - } - - void Initialize() { - idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; - idt_ptr.base = (uint64_t)&idt; - - for(int i = 0; i < 256; i++){ - SetGate(i, 0, 0x08, 0x8E); - } - - for(unsigned i = 48; i < 256; i++){ - SetGate(i, int_vectors[i - 48], 0x08, 0x8E); - } - - SetGate(0, (uint64_t)isr0,0x08,0x8E); - SetGate(1, (uint64_t)isr1,0x08,0x8E); - SetGate(2, (uint64_t)isr2,0x08,0x8E); - SetGate(3, (uint64_t)isr3,0x08,0x8E); - SetGate(4, (uint64_t)isr4,0x08,0x8E); - SetGate(5, (uint64_t)isr5,0x08,0x8E); - SetGate(6, (uint64_t)isr6,0x08,0x8E); - SetGate(7, (uint64_t)isr7,0x08,0x8E); - SetGate(8, (uint64_t)isr8,0x08,0x8E, 2); // Double Fault - SetGate(9, (uint64_t)isr9,0x08,0x8E); - SetGate(10, (uint64_t)isr10,0x08,0x8E); - SetGate(11, (uint64_t)isr11,0x08,0x8E); - SetGate(12, (uint64_t)isr12,0x08,0x8E); - SetGate(13, (uint64_t)isr13,0x08,0x8E); - SetGate(14, (uint64_t)isr14,0x08,0x8E); - SetGate(15, (uint64_t)isr15,0x08,0x8E); - SetGate(16, (uint64_t)isr16,0x08,0x8E); - SetGate(17, (uint64_t)isr17,0x08,0x8E); - SetGate(18, (uint64_t)isr18,0x08,0x8E); - SetGate(19, (uint64_t)isr19,0x08,0x8E); - SetGate(20, (uint64_t)isr20,0x08,0x8E); - SetGate(21, (uint64_t)isr21,0x08,0x8E); - SetGate(22, (uint64_t)isr22,0x08,0x8E); - SetGate(23, (uint64_t)isr23,0x08,0x8E); - SetGate(24, (uint64_t)isr24,0x08,0x8E); - SetGate(25, (uint64_t)isr25,0x08,0x8E); - SetGate(26, (uint64_t)isr26,0x08,0x8E); - SetGate(27, (uint64_t)isr27,0x08,0x8E); - SetGate(28, (uint64_t)isr28,0x08,0x8E); - SetGate(29, (uint64_t)isr29,0x08,0x8E); - SetGate(30, (uint64_t)isr30,0x08,0x8E); - SetGate(31, (uint64_t)isr31,0x08,0x8E); - SetGate(0x69, (uint64_t)isr0x69, 0x08, 0xEE /* Allow syscalls to be called from user mode*/, 0); // Syscall - - idt_flush(); - - outportb(0x20, 0x11); - outportb(0xA0, 0x11); - outportb(0x21, 0x20); - outportb(0xA1, 0x28); - outportb(0x21, 0x04); - outportb(0xA1, 0x02); - outportb(0x21, 0x01); - outportb(0xA1, 0x01); - outportb(0x21, 0x0); - outportb(0xA1, 0x0); - - SetGate(32, (uint64_t)irq0, 0x08, 0x8E); - SetGate(33, (uint64_t)irq1, 0x08, 0x8E); - SetGate(34, (uint64_t)irq2, 0x08, 0x8E); - SetGate(35, (uint64_t)irq3, 0x08, 0x8E); - SetGate(36, (uint64_t)irq4, 0x08, 0x8E); - SetGate(37, (uint64_t)irq5, 0x08, 0x8E); - SetGate(38, (uint64_t)irq6, 0x08, 0x8E); - SetGate(39, (uint64_t)irq7, 0x08, 0x8E); - SetGate(40, (uint64_t)irq8, 0x08, 0x8E); - SetGate(41, (uint64_t)irq9, 0x08, 0x8E); - SetGate(42, (uint64_t)irq10, 0x08, 0x8E); - SetGate(43, (uint64_t)irq11, 0x08, 0x8E); - SetGate(44, (uint64_t)irq12, 0x08, 0x8E); - SetGate(45, (uint64_t)irq13, 0x08, 0x8E); - SetGate(46, (uint64_t)irq14, 0x08, 0x8E); - SetGate(47, (uint64_t)irq15, 0x08, 0x8E); - - __asm__ __volatile__("sti"); - - RegisterInterruptHandler(IPI_HALT, IPIHalt); - } - - void RegisterInterruptHandler(uint8_t interrupt, isr_t handler, void* data) { - interrupt_handlers[interrupt] = {.handler = handler, .data = data}; - } - - uint8_t ReserveUnusedInterrupt(){ - uint8_t interrupt = 0xFF; - for(unsigned i = IRQ0 + 16 /* Ignore all legacy IRQs and exceptions */; i < 255 /* Ignore 0xFF */ && interrupt == 0xFF; i++){ - if(!interrupt_handlers[i].handler){ - interrupt_handlers[i].handler = InvalidInterruptHandler; - interrupt = i; - } - } - return interrupt; - } - - void DisablePIC(){ - outportb(0x20, 0x11); - outportb(0xA0, 0x11); - outportb(0x21, 0xF0); // Remap IRQs on both PICs to 0xF0-0xF8 - outportb(0xA1, 0xF0); - outportb(0x21, 0x04); - outportb(0xA1, 0x02); - outportb(0x21, 0x01); - outportb(0xA1, 0x01); - - outportb(0x21, 0xFF); // Mask all interrupts - outportb(0xA1, 0xFF); - } - - int GetErrCode(){ - return errCode; - } -} - -extern "C" - void isr_handler(int int_num, regs64_t* regs, int err_code) { - errCode = err_code; - if (interrupt_handlers[int_num].handler != 0) { - interrupt_handlers[int_num].handler(interrupt_handlers[int_num].data, regs); - } else if(int_num == 0x69){ - Log::Warning("\r\nEarly syscall"); - } else if(!(regs->ss & 0x3)){ // Check the CPL of the segment, caused by kernel? - // Kernel Panic so tell other processors to stop executing - APIC::Local::SendIPI(0, ICR_DSH_OTHER /* Send to all other processors except us */, ICR_MESSAGE_TYPE_FIXED, IPI_HALT); - - Log::Error("Fatal Kernel Exception: "); - Log::Info(int_num); - Log::Info("RIP: "); - Log::Info(regs->rip); - Log::Info("Error Code: "); - Log::Info(err_code); - Log::Info("Register Dump: a: "); - Log::Write(regs->rax); - Log::Write(", b:"); - Log::Write(regs->rbx); - Log::Write(", c:"); - Log::Write(regs->rcx); - Log::Write(", d:"); - Log::Write(regs->rdx); - Log::Write(", S:"); - Log::Write(regs->rsi); - Log::Write(", D:"); - Log::Write(regs->rdi); - Log::Write(", sp:"); - Log::Write(regs->rsp); - Log::Write(", bp:"); - Log::Write(regs->rbp); - - Log::Info("Stack Trace:"); - PrintStackTrace(regs->rbp); - - char temp[16]; - char temp2[16]; - char temp3[16]; - const char* reasons[]{"Generic Exception","RIP: ", itoa(regs->rip, temp, 16),"Exception: ",itoa(int_num, temp2, 16), "Process:", itoa(Scheduler::GetCurrentProcess() ? (Scheduler::GetCurrentProcess()->pid) : 0,temp3,10)};; - KernelPanic(reasons, 7); - for (;;); - } else { - Log::Warning("Process %s crashed, PID: ", Scheduler::GetCurrentProcess()->name); - Log::Write(Scheduler::GetCurrentProcess()->pid); - Log::Write(", RIP: "); - Log::Write(regs->rip); - Log::Write(", Exception: "); - Log::Write(int_num); - Log::Info("Stack trace:"); - UserPrintStackTrace(regs->rbp, Scheduler::GetCurrentProcess()->addressSpace); - Scheduler::EndProcess(Scheduler::GetCurrentProcess()); - } - } - - extern "C" - void irq_handler(int int_num, regs64_t* regs) { - LocalAPICEOI(); - - if (__builtin_expect(interrupt_handlers[int_num].handler != 0, 1)) { - ISRDataPair pair = interrupt_handlers[int_num]; - pair.handler(pair.data, regs); - } else { - Log::Warning("Unhandled IRQ: "); - Log::Write(int_num); - } - } - - extern "C" - void ipi_handler(int int_num, regs64_t* regs) { - LocalAPICEOI(); - - if (__builtin_expect(interrupt_handlers[int_num].handler != 0, 1)) { - ISRDataPair pair = interrupt_handlers[int_num]; - pair.handler(pair.data, regs); - } else { - Log::Warning("Unhandled IPI: "); - Log::Write(int_num); - } +#include +#include +#include +#include +#include +#include +#include +#include +#include + +idt_entry_t idt[256]; + +idt_ptr_t idt_ptr; + +struct ISRDataPair +{ + isr_t handler; + void* data; +}; +ISRDataPair interrupt_handlers[256]; + +extern "C" +void isr0(); +extern "C" +void isr1(); +extern "C" +void isr2(); +extern "C" +void isr3(); +extern "C" +void isr4(); +extern "C" +void isr5(); +extern "C" +void isr6(); +extern "C" +void isr7(); +extern "C" +void isr8(); +extern "C" +void isr9(); +extern "C" +void isr10(); +extern "C" +void isr11(); +extern "C" +void isr12(); +extern "C" +void isr13(); +extern "C" +void isr14(); +extern "C" +void isr15(); +extern "C" +void isr16(); +extern "C" +void isr17(); +extern "C" +void isr18(); +extern "C" +void isr19(); +extern "C" +void isr20(); +extern "C" +void isr21(); +extern "C" +void isr22(); +extern "C" +void isr23(); +extern "C" +void isr24(); +extern "C" +void isr25(); +extern "C" +void isr26(); +extern "C" +void isr27(); +extern "C" +void isr28(); +extern "C" +void isr29(); +extern "C" +void isr30(); +extern "C" +void isr31(); + +extern "C" +void irq0(); +extern "C" +void irq1(); +extern "C" +void irq2(); +extern "C" +void irq3(); +extern "C" +void irq4(); +extern "C" +void irq5(); +extern "C" +void irq6(); +extern "C" +void irq7(); +extern "C" +void irq8(); +extern "C" +void irq9(); +extern "C" +void irq10(); +extern "C" +void irq11(); +extern "C" +void irq12(); +extern "C" +void irq13(); +extern "C" +void irq14(); +extern "C" +void irq15(); + +extern "C" +void isr0x69(); + +extern "C" +void idt_flush(); + +extern uint64_t int_vectors[]; + +int errCode = 0; + +namespace IDT{ + void IPIHalt(void*, regs64_t* r){ + asm("cli"); + asm("hlt"); + } + + void InvalidInterruptHandler(void*, regs64_t* r){ + Log::Warning("Invalid interrupt handler called!"); + } + + static void SetGate(uint8_t num, uint64_t base, uint16_t sel, uint8_t flags, uint8_t ist = 0) { + idt[num].base_high = (base >> 32); + idt[num].base_med = (base >> 16) & 0xFFFF; + idt[num].base_low = base & 0xFFFF; + + idt[num].sel = sel; + idt[num].null = 0; + idt[num].ist = ist & 0x7; // Interrupt Stack Table (IST) + + idt[num].flags = flags; + } + + void Initialize() { + idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1; + idt_ptr.base = (uint64_t)&idt; + + for(int i = 0; i < 256; i++){ + SetGate(i, 0, 0x08, 0x8E); + } + + for(unsigned i = 48; i < 256; i++){ + SetGate(i, int_vectors[i - 48], 0x08, 0x8E); + } + + SetGate(0, (uint64_t)isr0,0x08,0x8E); + SetGate(1, (uint64_t)isr1,0x08,0x8E); + SetGate(2, (uint64_t)isr2,0x08,0x8E); + SetGate(3, (uint64_t)isr3,0x08,0x8E); + SetGate(4, (uint64_t)isr4,0x08,0x8E); + SetGate(5, (uint64_t)isr5,0x08,0x8E); + SetGate(6, (uint64_t)isr6,0x08,0x8E); + SetGate(7, (uint64_t)isr7,0x08,0x8E); + SetGate(8, (uint64_t)isr8,0x08,0x8E, 2); // Double Fault + SetGate(9, (uint64_t)isr9,0x08,0x8E); + SetGate(10, (uint64_t)isr10,0x08,0x8E); + SetGate(11, (uint64_t)isr11,0x08,0x8E); + SetGate(12, (uint64_t)isr12,0x08,0x8E); + SetGate(13, (uint64_t)isr13,0x08,0x8E); + SetGate(14, (uint64_t)isr14,0x08,0x8E); + SetGate(15, (uint64_t)isr15,0x08,0x8E); + SetGate(16, (uint64_t)isr16,0x08,0x8E); + SetGate(17, (uint64_t)isr17,0x08,0x8E); + SetGate(18, (uint64_t)isr18,0x08,0x8E); + SetGate(19, (uint64_t)isr19,0x08,0x8E); + SetGate(20, (uint64_t)isr20,0x08,0x8E); + SetGate(21, (uint64_t)isr21,0x08,0x8E); + SetGate(22, (uint64_t)isr22,0x08,0x8E); + SetGate(23, (uint64_t)isr23,0x08,0x8E); + SetGate(24, (uint64_t)isr24,0x08,0x8E); + SetGate(25, (uint64_t)isr25,0x08,0x8E); + SetGate(26, (uint64_t)isr26,0x08,0x8E); + SetGate(27, (uint64_t)isr27,0x08,0x8E); + SetGate(28, (uint64_t)isr28,0x08,0x8E); + SetGate(29, (uint64_t)isr29,0x08,0x8E); + SetGate(30, (uint64_t)isr30,0x08,0x8E); + SetGate(31, (uint64_t)isr31,0x08,0x8E); + SetGate(0x69, (uint64_t)isr0x69, 0x08, 0xEE /* Allow syscalls to be called from user mode*/, 0); // Syscall + + idt_flush(); + + outportb(0x20, 0x11); + outportb(0xA0, 0x11); + outportb(0x21, 0x20); + outportb(0xA1, 0x28); + outportb(0x21, 0x04); + outportb(0xA1, 0x02); + outportb(0x21, 0x01); + outportb(0xA1, 0x01); + outportb(0x21, 0x0); + outportb(0xA1, 0x0); + + SetGate(32, (uint64_t)irq0, 0x08, 0x8E); + SetGate(33, (uint64_t)irq1, 0x08, 0x8E); + SetGate(34, (uint64_t)irq2, 0x08, 0x8E); + SetGate(35, (uint64_t)irq3, 0x08, 0x8E); + SetGate(36, (uint64_t)irq4, 0x08, 0x8E); + SetGate(37, (uint64_t)irq5, 0x08, 0x8E); + SetGate(38, (uint64_t)irq6, 0x08, 0x8E); + SetGate(39, (uint64_t)irq7, 0x08, 0x8E); + SetGate(40, (uint64_t)irq8, 0x08, 0x8E); + SetGate(41, (uint64_t)irq9, 0x08, 0x8E); + SetGate(42, (uint64_t)irq10, 0x08, 0x8E); + SetGate(43, (uint64_t)irq11, 0x08, 0x8E); + SetGate(44, (uint64_t)irq12, 0x08, 0x8E); + SetGate(45, (uint64_t)irq13, 0x08, 0x8E); + SetGate(46, (uint64_t)irq14, 0x08, 0x8E); + SetGate(47, (uint64_t)irq15, 0x08, 0x8E); + + __asm__ __volatile__("sti"); + + RegisterInterruptHandler(IPI_HALT, IPIHalt); + } + + void RegisterInterruptHandler(uint8_t interrupt, isr_t handler, void* data) { + interrupt_handlers[interrupt] = {.handler = handler, .data = data}; + } + + uint8_t ReserveUnusedInterrupt(){ + uint8_t interrupt = 0xFF; + for(unsigned i = IRQ0 + 16 /* Ignore all legacy IRQs and exceptions */; i < 255 /* Ignore 0xFF */ && interrupt == 0xFF; i++){ + if(!interrupt_handlers[i].handler){ + interrupt_handlers[i].handler = InvalidInterruptHandler; + interrupt = i; + } + } + return interrupt; + } + + void DisablePIC(){ + outportb(0x20, 0x11); + outportb(0xA0, 0x11); + outportb(0x21, 0xF0); // Remap IRQs on both PICs to 0xF0-0xF8 + outportb(0xA1, 0xF0); + outportb(0x21, 0x04); + outportb(0xA1, 0x02); + outportb(0x21, 0x01); + outportb(0xA1, 0x01); + + outportb(0x21, 0xFF); // Mask all interrupts + outportb(0xA1, 0xFF); + } + + int GetErrCode(){ + return errCode; + } +} + +extern "C" + void isr_handler(int int_num, regs64_t* regs, int err_code) { + errCode = err_code; + if (interrupt_handlers[int_num].handler != 0) { + interrupt_handlers[int_num].handler(interrupt_handlers[int_num].data, regs); + } else if(int_num == 0x69){ + Log::Warning("\r\nEarly syscall"); + } else if(!(regs->ss & 0x3)){ // Check the CPL of the segment, caused by kernel? + // Kernel Panic so tell other processors to stop executing + APIC::Local::SendIPI(0, ICR_DSH_OTHER /* Send to all other processors except us */, ICR_MESSAGE_TYPE_FIXED, IPI_HALT); + + Log::Error("Fatal Kernel Exception: "); + Log::Info(int_num); + Log::Info("RIP: "); + Log::Info(regs->rip); + Log::Info("Error Code: "); + Log::Info(err_code); + Log::Info("Register Dump: a: "); + Log::Write(regs->rax); + Log::Write(", b:"); + Log::Write(regs->rbx); + Log::Write(", c:"); + Log::Write(regs->rcx); + Log::Write(", d:"); + Log::Write(regs->rdx); + Log::Write(", S:"); + Log::Write(regs->rsi); + Log::Write(", D:"); + Log::Write(regs->rdi); + Log::Write(", sp:"); + Log::Write(regs->rsp); + Log::Write(", bp:"); + Log::Write(regs->rbp); + + Log::Info("Stack Trace:"); + PrintStackTrace(regs->rbp); + + char temp[16]; + char temp2[16]; + char temp3[16]; + const char* reasons[]{"Generic Exception","RIP: ", itoa(regs->rip, temp, 16),"Exception: ",itoa(int_num, temp2, 16), "Process:", itoa(Scheduler::GetCurrentProcess() ? (Scheduler::GetCurrentProcess()->pid) : 0,temp3,10)};; + KernelPanic(reasons, 7); + for (;;); + } else { + Log::Warning("Process %s crashed, PID: ", Scheduler::GetCurrentProcess()->name); + Log::Write(Scheduler::GetCurrentProcess()->pid); + Log::Write(", RIP: "); + Log::Write(regs->rip); + Log::Write(", Exception: "); + Log::Write(int_num); + Log::Info("Stack trace:"); + UserPrintStackTrace(regs->rbp, Scheduler::GetCurrentProcess()->addressSpace); + Scheduler::EndProcess(Scheduler::GetCurrentProcess()); + } + } + + extern "C" + void irq_handler(int int_num, regs64_t* regs) { + LocalAPICEOI(); + + if (__builtin_expect(interrupt_handlers[int_num].handler != 0, 1)) { + ISRDataPair pair = interrupt_handlers[int_num]; + pair.handler(pair.data, regs); + } else { + Log::Warning("Unhandled IRQ: "); + Log::Write(int_num); + } + } + + extern "C" + void ipi_handler(int int_num, regs64_t* regs) { + LocalAPICEOI(); + + if (__builtin_expect(interrupt_handlers[int_num].handler != 0, 1)) { + ISRDataPair pair = interrupt_handlers[int_num]; + pair.handler(pair.data, regs); + } else { + Log::Warning("Unhandled IPI: "); + Log::Write(int_num); + } } \ No newline at end of file diff --git a/Kernel/src/arch/x86_64/keyboard.cpp b/Kernel/src/arch/x86_64/keyboard.cpp index 2b6a6bf8..0a189dd0 100755 --- a/Kernel/src/arch/x86_64/keyboard.cpp +++ b/Kernel/src/arch/x86_64/keyboard.cpp @@ -1,90 +1,90 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define KEY_QUEUE_SIZE 256 - -namespace Keyboard{ - uint8_t keyQueue[KEY_QUEUE_SIZE]; - - unsigned short keyQueueEnd = 0; - unsigned short keyQueueStart = 0; - unsigned short keyCount = 0; - - bool ReadKey(uint8_t* key){ - if(keyCount <= 0) return false; - - *key = keyQueue[keyQueueStart]; - - keyQueueStart++; - - if(keyQueueStart >= KEY_QUEUE_SIZE) { - keyQueueStart = 0; - } - - keyCount--; - - return true; - } - - class KeyboardDevice : public Device{ - public: - DirectoryEntry dirent; - - KeyboardDevice(char* name) : Device(name, TypeInputDevice){ - flags = FS_NODE_CHARDEVICE; - strcpy(dirent.name, name); - dirent.flags = flags; - dirent.node = this; - } - - ssize_t Read(size_t offset, size_t size, uint8_t *buffer){ - if(size > keyCount) size = keyCount; - - if(!size) return 0; - - for(unsigned short i = 0; i < size; i++){ - ReadKey(buffer++); // Insert key and increment - } - - return size; - } - }; - - KeyboardDevice kbDev("keyboard0"); - - // Interrupt handler - void Handler(void*, regs64_t* r) - { - // Read from the keyboard's data buffer - uint8_t key = inportb(0x60); - - if(keyCount >= KEY_QUEUE_SIZE) return; // Drop key - - // Add key to queue - keyQueue[keyQueueEnd] = key; - - keyQueueEnd++; - - if(keyQueueEnd >= KEY_QUEUE_SIZE) { - keyQueueEnd = 0; - } - - keyCount++; - } - - // Register interrupt handler - void Install() { - DeviceManager::RegisterDevice(kbDev); - - IDT::RegisterInterruptHandler(IRQ0 + 1, Handler); - APIC::IO::MapLegacyIRQ(1); - - outportb(0xF0, 1); // Set scan code 1 - } -} +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEY_QUEUE_SIZE 256 + +namespace Keyboard{ + uint8_t keyQueue[KEY_QUEUE_SIZE]; + + unsigned short keyQueueEnd = 0; + unsigned short keyQueueStart = 0; + unsigned short keyCount = 0; + + bool ReadKey(uint8_t* key){ + if(keyCount <= 0) return false; + + *key = keyQueue[keyQueueStart]; + + keyQueueStart++; + + if(keyQueueStart >= KEY_QUEUE_SIZE) { + keyQueueStart = 0; + } + + keyCount--; + + return true; + } + + class KeyboardDevice : public Device{ + public: + DirectoryEntry dirent; + + KeyboardDevice(char* name) : Device(name, TypeInputDevice){ + flags = FS_NODE_CHARDEVICE; + strcpy(dirent.name, name); + dirent.flags = flags; + dirent.node = this; + } + + ssize_t Read(size_t offset, size_t size, uint8_t *buffer){ + if(size > keyCount) size = keyCount; + + if(!size) return 0; + + for(unsigned short i = 0; i < size; i++){ + ReadKey(buffer++); // Insert key and increment + } + + return size; + } + }; + + KeyboardDevice kbDev("keyboard0"); + + // Interrupt handler + void Handler(void*, regs64_t* r) + { + // Read from the keyboard's data buffer + uint8_t key = inportb(0x60); + + if(keyCount >= KEY_QUEUE_SIZE) return; // Drop key + + // Add key to queue + keyQueue[keyQueueEnd] = key; + + keyQueueEnd++; + + if(keyQueueEnd >= KEY_QUEUE_SIZE) { + keyQueueEnd = 0; + } + + keyCount++; + } + + // Register interrupt handler + void Install() { + DeviceManager::RegisterDevice(kbDev); + + IDT::RegisterInterruptHandler(IRQ0 + 1, Handler); + APIC::IO::MapLegacyIRQ(1); + + outportb(0xF0, 1); // Set scan code 1 + } +} diff --git a/Kernel/src/arch/x86_64/mouse.cpp b/Kernel/src/arch/x86_64/mouse.cpp index 74f8683b..d8f114eb 100755 --- a/Kernel/src/arch/x86_64/mouse.cpp +++ b/Kernel/src/arch/x86_64/mouse.cpp @@ -1,181 +1,181 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PACKET_QUEUE_SIZE 64 - -namespace Mouse{ - int8_t mouseData[3]; - - struct MousePacket{ - int8_t buttons; - int8_t xMovement; - int8_t yMovement; - int8_t verticalScroll; - }; - - MousePacket packetQueue[PACKET_QUEUE_SIZE]; // Use a statically allocated array to avoid allocations - - short packetQueueEnd = 0; - short packetQueueStart = 0; - short packetCount = 0; - - uint8_t mouseCycle = 0; - - bool dataUpdated = false; - - void Handler(void*, regs64_t* regs) { - switch (mouseCycle) - { - case 0: - mouseData[0] = inportb(0x60); - - if(!(mouseData[0] & 0x8)) break; - - mouseCycle++; - break; - case 1: - mouseData[1] = inportb(0x60); - mouseCycle++; - break; - case 2: { - mouseData[2] = inportb(0x60); - mouseCycle = 0; - - if(packetCount >= PACKET_QUEUE_SIZE) break; // Drop packet - - MousePacket pkt; - pkt.buttons = mouseData[0] & (MOUSE_BUTTON_LEFT | MOUSE_BUTTON_MIDDLE | MOUSE_BUTTON_RIGHT); - - pkt.xMovement = mouseData[1]; - pkt.yMovement = -mouseData[2]; - - // Add packet to queue - packetQueue[packetQueueEnd] = pkt; - - packetQueueEnd++; - - if(packetQueueEnd >= PACKET_QUEUE_SIZE) { - packetQueueEnd = 0; - } - - packetCount++; - - break; - } default: { - mouseCycle = 0; - break; - } - } - } - - inline void Wait(uint8_t type) - { - int timeout = 100000; - if (type == 0) { - while (timeout--) //Data - if ((inportb(0x64) & 1) == 1) - return; - } else - while (timeout--) //Signal - if ((inportb(0x64) & 2) == 0) - return; - } - - inline void Write(uint8_t data) - { - Wait(1); - outportb(0x64, 0xD4); - Wait(1); - //Send data - outportb(0x60, data); - } - - uint8_t Read() - { - //Get's response from mouse - Wait(0); - return inportb(0x60); - } - - bool DataUpdated() { - bool updated = dataUpdated; - if(dataUpdated) - dataUpdated = false; - return updated; - } - - class MouseDevice : public Device{ - public: - DirectoryEntry dirent; - - MouseDevice(char* name) : Device(name, TypeInputDevice){ - flags = FS_NODE_CHARDEVICE; - strcpy(dirent.name, name); - dirent.flags = flags; - dirent.node = this; - } - - ssize_t Read(size_t offset, size_t size, uint8_t *buffer){ - if(size < sizeof(MousePacket)) return 0; - - if(packetCount <= 0) return 0; // No packets - - MousePacket* pkt = (MousePacket*)buffer; - *pkt = packetQueue[packetQueueStart]; - - packetQueueStart++; - - if(packetQueueStart >= PACKET_QUEUE_SIZE) { - packetQueueStart = 0; - } - - packetCount--; - - return sizeof(MousePacket); - } - }; - - MouseDevice mouseDev("mouse0"); - - void Install() - { - Wait(1); - outportb(0x64, 0xA8); // Enable aux PS/2 input - - outportb(0x64, 0xFF); // Reset Mouse - - //Enable the interrupts - Wait(1); - outportb(0x64, 0x20); - Wait(0); - uint8_t status = ((inportb(0x60) & ~0x20) | 2); // Enable interrupts, enable mouse clock - Wait(1); - outportb(0x64, 0x60); - Wait(1); - outportb(0x60, status); - - Write(0xF6); - Read(); - - Write(0xF4); - Read(); - - IDT::RegisterInterruptHandler(IRQ0 + 12, Handler); - APIC::IO::MapLegacyIRQ(12); - - DeviceManager::RegisterDevice(mouseDev); - } - - int8_t* GetData() { - return mouseData; - } +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PACKET_QUEUE_SIZE 64 + +namespace Mouse{ + int8_t mouseData[3]; + + struct MousePacket{ + int8_t buttons; + int8_t xMovement; + int8_t yMovement; + int8_t verticalScroll; + }; + + MousePacket packetQueue[PACKET_QUEUE_SIZE]; // Use a statically allocated array to avoid allocations + + short packetQueueEnd = 0; + short packetQueueStart = 0; + short packetCount = 0; + + uint8_t mouseCycle = 0; + + bool dataUpdated = false; + + void Handler(void*, regs64_t* regs) { + switch (mouseCycle) + { + case 0: + mouseData[0] = inportb(0x60); + + if(!(mouseData[0] & 0x8)) break; + + mouseCycle++; + break; + case 1: + mouseData[1] = inportb(0x60); + mouseCycle++; + break; + case 2: { + mouseData[2] = inportb(0x60); + mouseCycle = 0; + + if(packetCount >= PACKET_QUEUE_SIZE) break; // Drop packet + + MousePacket pkt; + pkt.buttons = mouseData[0] & (MOUSE_BUTTON_LEFT | MOUSE_BUTTON_MIDDLE | MOUSE_BUTTON_RIGHT); + + pkt.xMovement = mouseData[1]; + pkt.yMovement = -mouseData[2]; + + // Add packet to queue + packetQueue[packetQueueEnd] = pkt; + + packetQueueEnd++; + + if(packetQueueEnd >= PACKET_QUEUE_SIZE) { + packetQueueEnd = 0; + } + + packetCount++; + + break; + } default: { + mouseCycle = 0; + break; + } + } + } + + inline void Wait(uint8_t type) + { + int timeout = 100000; + if (type == 0) { + while (timeout--) //Data + if ((inportb(0x64) & 1) == 1) + return; + } else + while (timeout--) //Signal + if ((inportb(0x64) & 2) == 0) + return; + } + + inline void Write(uint8_t data) + { + Wait(1); + outportb(0x64, 0xD4); + Wait(1); + //Send data + outportb(0x60, data); + } + + uint8_t Read() + { + //Get's response from mouse + Wait(0); + return inportb(0x60); + } + + bool DataUpdated() { + bool updated = dataUpdated; + if(dataUpdated) + dataUpdated = false; + return updated; + } + + class MouseDevice : public Device{ + public: + DirectoryEntry dirent; + + MouseDevice(char* name) : Device(name, TypeInputDevice){ + flags = FS_NODE_CHARDEVICE; + strcpy(dirent.name, name); + dirent.flags = flags; + dirent.node = this; + } + + ssize_t Read(size_t offset, size_t size, uint8_t *buffer){ + if(size < sizeof(MousePacket)) return 0; + + if(packetCount <= 0) return 0; // No packets + + MousePacket* pkt = (MousePacket*)buffer; + *pkt = packetQueue[packetQueueStart]; + + packetQueueStart++; + + if(packetQueueStart >= PACKET_QUEUE_SIZE) { + packetQueueStart = 0; + } + + packetCount--; + + return sizeof(MousePacket); + } + }; + + MouseDevice mouseDev("mouse0"); + + void Install() + { + Wait(1); + outportb(0x64, 0xA8); // Enable aux PS/2 input + + outportb(0x64, 0xFF); // Reset Mouse + + //Enable the interrupts + Wait(1); + outportb(0x64, 0x20); + Wait(0); + uint8_t status = ((inportb(0x60) & ~0x20) | 2); // Enable interrupts, enable mouse clock + Wait(1); + outportb(0x64, 0x60); + Wait(1); + outportb(0x60, status); + + Write(0xF6); + Read(); + + Write(0xF4); + Read(); + + IDT::RegisterInterruptHandler(IRQ0 + 12, Handler); + APIC::IO::MapLegacyIRQ(12); + + DeviceManager::RegisterDevice(mouseDev); + } + + int8_t* GetData() { + return mouseData; + } } \ No newline at end of file diff --git a/Kernel/src/arch/x86_64/paging.cpp b/Kernel/src/arch/x86_64/paging.cpp index a47852a0..eed89d3c 100755 --- a/Kernel/src/arch/x86_64/paging.cpp +++ b/Kernel/src/arch/x86_64/paging.cpp @@ -1,658 +1,658 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//extern uint32_t kernel_end; - -#define KERNEL_HEAP_PDPT_INDEX 511 -#define KERNEL_HEAP_PML4_INDEX 511 - -address_space_t* currentAddressSpace; - -uint64_t kernelPML4Phys; -extern int lastSyscall; - -namespace Memory{ - pml4_t kernelPML4 __attribute__((aligned(4096))); - pdpt_t kernelPDPT __attribute__((aligned(4096))); // Kernel itself will reside here (0xFFFFFFFF80000000) - page_dir_t kernelDir __attribute__((aligned(4096))); - page_dir_t kernelHeapDir __attribute__((aligned(4096))); - page_t kernelHeapDirTables[TABLES_PER_DIR][PAGES_PER_TABLE] __attribute__((aligned(4096))); - page_dir_t ioDirs[4] __attribute__((aligned(4096))); - - uint64_t VirtualToPhysicalAddress(uint64_t addr) { - uint64_t address = 0; - - uint32_t pml4Index = PML4_GET_INDEX(addr); - uint32_t pageDirIndex = PAGE_DIR_GET_INDEX(addr); - uint32_t pageTableIndex = PAGE_TABLE_GET_INDEX(addr); - - if(pml4Index < 511){ // From Process Address Space - - } else { // From Kernel Address Space - if(kernelHeapDir[pageDirIndex] & 0x80){ - address = (GetPageFrame(kernelHeapDir[pageDirIndex])) << 12; - } else { - address = (GetPageFrame(kernelHeapDirTables[pageDirIndex][pageTableIndex])) << 12; - } - } - return address; - } - - uint64_t VirtualToPhysicalAddress(uint64_t addr, address_space_t* addressSpace) { - uint64_t address = 0; - - uint32_t pml4Index = PML4_GET_INDEX(addr); - uint32_t pdptIndex = PDPT_GET_INDEX(addr); - uint32_t pageDirIndex = PAGE_DIR_GET_INDEX(addr); - uint32_t pageTableIndex = PAGE_TABLE_GET_INDEX(addr); - - if(pml4Index == 0){ // From Process Address Space - if((addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1) && addressSpace->pageTables[pdptIndex][pageDirIndex]) - return addressSpace->pageTables[pdptIndex][pageDirIndex][pageTableIndex] & PAGE_FRAME; - else return 0; - } else { // From Kernel Address Space - if(kernelHeapDir[pageDirIndex] & 0x80){ - address = (GetPageFrame(kernelHeapDir[pageDirIndex])) << 12; - } else { - address = (GetPageFrame(kernelHeapDirTables[pageDirIndex][pageTableIndex])) << 12; - } - } - return address; - } - - void InitializeVirtualMemory() - { - IDT::RegisterInterruptHandler(14,PageFaultHandler); - memset(kernelPML4, 0, sizeof(pml4_t)); - memset(kernelPDPT, 0, sizeof(pdpt_t)); - memset(kernelHeapDir, 0, sizeof(page_dir_t)); - - SetPageFrame(&(kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)]),((uint64_t)kernelPDPT - KERNEL_VIRTUAL_BASE)); - kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)] |= 0x3; - kernelPML4[0] = kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)]; - - kernelPDPT[PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)] = ((uint64_t)kernelDir - KERNEL_VIRTUAL_BASE) | 0x3; - for(int j = 0; j < TABLES_PER_DIR; j++){ - kernelDir[j] = (PAGE_SIZE_2M * j) | 0x83; - } - - kernelPDPT[KERNEL_HEAP_PDPT_INDEX] = 0x3; - SetPageFrame(&(kernelPDPT[KERNEL_HEAP_PDPT_INDEX]), (uint64_t)kernelHeapDir - KERNEL_VIRTUAL_BASE); - - for(int i = 0; i < 4; i++){ - kernelPDPT[PDPT_GET_INDEX(IO_VIRTUAL_BASE) + i] = ((uint64_t)ioDirs[i] - KERNEL_VIRTUAL_BASE) | 0x3;//(PAGE_SIZE_1G * i) | 0x83; - for(int j = 0; j < TABLES_PER_DIR; j++){ - ioDirs[i][j] = (PAGE_SIZE_1G * i + PAGE_SIZE_2M * j) | (PDE_2M | PDE_WRITABLE | PDE_PRESENT | PDE_CACHE_DISABLED); - } - } - - kernelPDPT[0] = kernelPDPT[PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)]; // Its important that we identity map low memory for SMP - - for(int i = 0; i < TABLES_PER_DIR; i++){ - memset(&(kernelHeapDirTables[i]),0,sizeof(page_t)*PAGES_PER_TABLE); - } - - kernelPML4Phys = (uint64_t)kernelPML4 - KERNEL_VIRTUAL_BASE; - asm("mov %%rax, %%cr3" :: "a"((uint64_t)kernelPML4 - KERNEL_VIRTUAL_BASE)); - } - - address_space_t* CreateAddressSpace(){ - address_space_t* addressSpace = (address_space_t*)kmalloc(sizeof(address_space_t)); - - pdpt_entry_t* pdpt = (pdpt_entry_t*)Memory::KernelAllocate4KPages(1); // PDPT; - uintptr_t pdptPhys = Memory::AllocatePhysicalMemoryBlock(); - Memory::KernelMapVirtualMemory4K(pdptPhys, (uintptr_t)pdpt,1); - memset((pdpt_entry_t*)pdpt,0,4096); - - pd_entry_t** pageDirs = (pd_entry_t**)KernelAllocate4KPages(1); // Page Dirs - Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageDirs,1); - uint64_t* pageDirsPhys = (uint64_t*)KernelAllocate4KPages(1); // Page Dirs - Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageDirsPhys,1); - page_t*** pageTables = (page_t***)KernelAllocate4KPages(1); // Page Tables - Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageTables,1); - - pml4_entry_t* pml4 = (pml4_entry_t*)KernelAllocate4KPages(1); // Page Tables - uintptr_t pml4Phys = Memory::AllocatePhysicalMemoryBlock(); - Memory::KernelMapVirtualMemory4K(pml4Phys, (uintptr_t)pml4,1); - memcpy(pml4, kernelPML4, 4096); - - for(int i = 0; i < 512; i++){ - pageDirs[i] = (pd_entry_t*)KernelAllocate4KPages(1); - pageDirsPhys[i] = Memory::AllocatePhysicalMemoryBlock(); - KernelMapVirtualMemory4K(pageDirsPhys[i],(uintptr_t)pageDirs[i],1); - - pageTables[i] = (page_t**)Memory::KernelAllocate4KPages(1); - KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(),(uintptr_t)pageTables[i],1); - - SetPageFrame(&(pdpt[i]),pageDirsPhys[i]); - pdpt[i] |= PDPT_WRITABLE | PDPT_PRESENT | PDPT_USER; - - memset(pageDirs[i],0,4096); - memset(pageTables[i],0,4096); - } - - addressSpace->pageDirs = pageDirs; - addressSpace->pageDirsPhys = pageDirsPhys; - addressSpace->pageTables = pageTables; - addressSpace->pml4 = pml4; - addressSpace->pdptPhys = pdptPhys; - addressSpace->pml4Phys = pml4Phys; - addressSpace->pdpt = pdpt; - - pml4[0] = pdptPhys | PML4_PRESENT | PML4_WRITABLE | PAGE_USER; - - return addressSpace; - } - - void DestroyAddressSpace(address_space_t* addressSpace){ - for(int i = 0; i < DIRS_PER_PDPT; i++){ - for(int j = 0; j < TABLES_PER_DIR; j++){ - pd_entry_t dirEnt = addressSpace->pageDirs[i][j]; - if(dirEnt & PAGE_PRESENT){ - uint64_t phys = GetPageFrame(dirEnt); - - for(int k = 0; k < PAGES_PER_TABLE; k++){ - if(addressSpace->pageTables[i][j][k] & 0x1){ - uint64_t pagePhys = GetPageFrame(addressSpace->pageTables[i][j][k]); - FreePhysicalMemoryBlock(pagePhys); - } - } - - FreePhysicalMemoryBlock(phys); - addressSpace->pageDirs[i][j] = 0; - KernelFree4KPages(addressSpace->pageTables[i][j], 1); - } - addressSpace->pageDirs[i][j] = 0; - } - - addressSpace->pdpt[i] = 0; - Memory::FreePhysicalMemoryBlock(addressSpace->pageDirsPhys[i]); - KernelFree4KPages(addressSpace->pageDirs[i], 1); - } - } - - bool CheckRegion(uintptr_t addr, uint64_t len, address_space_t* addressSpace){ - return addr < PDPT_SIZE && (addr + len) < PDPT_SIZE && (addressSpace->pdpt[PDPT_GET_INDEX(addr)] & PDPT_USER) && (addressSpace->pdpt[PDPT_GET_INDEX(addr + len)] & PDPT_USER); - } - - bool CheckKernelPointer(uintptr_t addr, uint64_t len){ - if(PML4_GET_INDEX(addr) != PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)){ - return 0; - } - - if(!(kernelPDPT[PDPT_GET_INDEX(addr)] & 0x1)){ - return 0; - } - - if(PDPT_GET_INDEX(addr) == KERNEL_HEAP_PDPT_INDEX){ - if(!(kernelHeapDir[PAGE_DIR_GET_INDEX(addr)] & 0x1)){ - return 0; - } - - if(!(kernelHeapDir[PAGE_DIR_GET_INDEX(addr)] & PDE_2M)){ - if(!(kernelHeapDirTables[PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & 0x1)){ - return 0; - } - } - } else if(PDPT_GET_INDEX(addr) == PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)){ - if(!(kernelDir[PAGE_DIR_GET_INDEX(addr)] & 0x1)){ - return 0; - } - } else { - return 0; - } - - return 1; - } - - bool CheckUsermodePointer(uintptr_t addr, uint64_t len, address_space_t* addressSpace){ - if(addr >> 48) return 0; // Non-canonical or higher-half address - - if(!(addressSpace->pageDirs[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)] & (PAGE_PRESENT))){ - return 0; - } - - if(!(addressSpace->pageDirs[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)] & (PAGE_PRESENT))){ - return 0; - } - - if(!((addressSpace->pageTables[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & (PAGE_PRESENT)) && addressSpace->pageTables[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & (PAGE_USER))){ - return 0; - } - - if(!((addressSpace->pageTables[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)][PAGE_TABLE_GET_INDEX(addr + len)] & (PAGE_PRESENT)) && addressSpace->pageTables[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)][PAGE_TABLE_GET_INDEX(addr + len)] & (PAGE_USER))){ - return 0; - } - - return 1; - } - - page_table_t AllocatePageTable(){ - void* virt = KernelAllocate4KPages(1); - uint64_t phys = Memory::AllocatePhysicalMemoryBlock(); - - KernelMapVirtualMemory4K(phys,(uintptr_t)virt, 1); - - page_table_t pTable; - pTable.phys = phys; - pTable.virt = (page_t*)virt; - - for(int i = 0; i < PAGES_PER_TABLE; i++){ - ((page_t*)virt)[i] = 0; - } - - return pTable; - } - - void CreatePageTable(uint16_t pdptIndex, uint16_t pageDirIndex, address_space_t* addressSpace){ - page_table_t pTable = AllocatePageTable(); - SetPageFrame(&(addressSpace->pageDirs[pdptIndex][pageDirIndex]),pTable.phys); - addressSpace->pageDirs[pdptIndex][pageDirIndex] |= PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; - addressSpace->pageTables[pdptIndex][pageDirIndex] = pTable.virt; - } - - void* Allocate4KPages(uint64_t amount, address_space_t* addressSpace){ - uint64_t offset = 0; - uint64_t pageDirOffset = 0; - uint64_t counter = 0; - uintptr_t address = 0; - - uint64_t pml4Index = 0; - for(int d = 0; d < 512; d++){ - uint64_t pdptIndex = d; - if(!(addressSpace->pdpt[d] & 0x1)) break; - /* Attempt 1: Already Allocated Page Tables*/ - for(int i = 0; i < TABLES_PER_DIR; i++){ - if(addressSpace->pageDirs[d][i] & 0x1 && !(addressSpace->pageDirs[d][i] & 0x80)){ - for(int j = 0; j < PAGES_PER_TABLE; j++){ - if(addressSpace->pageTables[d][i][j] & 0x1){ - pageDirOffset = i; - offset = j+1; - counter = 0; - continue; - } - - counter++; - - if(counter >= amount){ - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); - while(counter--){ - if(offset >= 512){ - pageDirOffset++; - offset = 0; - } - addressSpace->pageTables[d][pageDirOffset][offset] = 0x3; - offset++; - } - - return (void*)address; - } - } - } else { - pageDirOffset = i+1; - offset = 0; - counter = 0; - } - } - - pageDirOffset = 0; - offset = 0; - counter = 0; - - /* Attempt 2: Allocate Page Tables*/ - for(int i = 0; i < TABLES_PER_DIR; i++){ - if(!(addressSpace->pageDirs[d][i] & 0x1)){ - - CreatePageTable(d,i,addressSpace); - for(int j = 0; j < PAGES_PER_TABLE; j++){ - - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); - counter++; - - if(counter >= amount){ - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); - while(counter--){ - if(offset >= 512){ - pageDirOffset ++; - offset = 0; - } - addressSpace->pageTables[d][pageDirOffset][offset] = 0x3; - offset++; - } - return (void*)address; - } - } - } else { - pageDirOffset = i+1; - offset = 0; - counter = 0; - } - } - Log::Info("new dir"); - } - - const char* reasons[1] = {"Out of Virtual Memory!"}; - KernelPanic(reasons, 1); - } - - void* KernelAllocate4KPages(uint64_t amount){ - uint64_t offset = 0; - uint64_t pageDirOffset = 0; - uint64_t counter = 0; - uintptr_t address = 0; - - uint64_t pml4Index = KERNEL_HEAP_PML4_INDEX; - uint64_t pdptIndex = KERNEL_HEAP_PDPT_INDEX; - - /* Attempt 1: Already Allocated Page Tables*/ - for(int i = 0; i < TABLES_PER_DIR; i++){ - if(kernelHeapDir[i] & 0x1 && !(kernelHeapDir[i] & 0x80)){ - for(int j = 0; j < TABLES_PER_DIR; j++){ - if(kernelHeapDirTables[i][j] & 0x1){ - pageDirOffset = i; - offset = j+1; - counter = 0; - continue; - } - - counter++; - - if(counter >= amount){ - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); - address |= 0xFFFF000000000000; - while(counter--){ - if(offset >= 512){ - pageDirOffset++; - offset = 0; - } - kernelHeapDirTables[pageDirOffset][offset] = 0x3; - offset++; - } - - return (void*)address; - } - } - } else { - pageDirOffset = i+1; - offset = 0; - counter = 0; - } - } - - pageDirOffset = 0; - offset = 0; - counter = 0; - - /* Attempt 2: Allocate Page Tables*/ - for(int i = 0; i < TABLES_PER_DIR; i++){ - if(!(kernelHeapDir[i] & 0x1)){ - counter += 512; - - if(counter >= amount){ - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); - address |= 0xFFFF000000000000; - //kernelHeapDir[i] = (PAGE_FRAME & ((uintptr_t)&(kernelHeapDirTables[i]) - KERNEL_VIRTUAL_BASE)) | 0x3; - SetPageFrame(&(kernelHeapDir[pageDirOffset]),((uintptr_t)&(kernelHeapDirTables[pageDirOffset]) - KERNEL_VIRTUAL_BASE)); - kernelHeapDir[pageDirOffset] |= 0x3; - while(amount--){ - if(offset >= 512){ - pageDirOffset ++; - offset = 0; - SetPageFrame(&(kernelHeapDir[pageDirOffset]),((uintptr_t)&(kernelHeapDirTables[pageDirOffset]) - KERNEL_VIRTUAL_BASE)); - kernelHeapDir[pageDirOffset] |= 0x3; - } - kernelHeapDirTables[pageDirOffset][offset] = 0x3; - offset++; - } - return (void*)address; - } - } else { - pageDirOffset = i+1; - offset = 0; - counter = 0; - } - } - - Log::Error("Kernel Out of Virtual Memory"); - const char* reasons[1] = {"Kernel Out of Virtual Memory!"}; - KernelPanic(reasons, 1); - } - - void* KernelAllocate2MPages(uint64_t amount){ - uint64_t address = 0; - uint64_t offset = 0; - uint64_t counter = 0; - uint64_t pdptIndex = KERNEL_HEAP_PDPT_INDEX; - uint64_t pml4Index = KERNEL_HEAP_PML4_INDEX; - - for(int i = 0; i < TABLES_PER_DIR; i++){ - if(kernelHeapDir[i] & 0x1){ - offset = i+1; - counter = 0; - continue; - } - counter++; - - if(counter >= amount){ - address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + offset * PAGE_SIZE_2M; - address |= 0xFFFF000000000000; - while(counter--){ - kernelHeapDir[offset] = 0x83; - offset++; - } - return (void*)address; - } - } - - Log::Error("Kernel Out of Virtual Memory"); - const char* reasons[1] = {"Kernel Out of Virtual Memory!"}; - KernelPanic(reasons, 1); - for(;;); - } - - void KernelFree4KPages(void* addr, uint64_t amount){ - uint64_t pageDirIndex, pageIndex; - uint64_t virt = (uint64_t)addr; - - while(amount--){ - pageDirIndex = PAGE_DIR_GET_INDEX(virt); - pageIndex = PAGE_TABLE_GET_INDEX(virt); - kernelHeapDirTables[pageDirIndex][pageIndex] = 0; - invlpg(virt); - virt += PAGE_SIZE_4K; - } - } - - void KernelFree2MPages(void* addr, uint64_t amount){ - while(amount--){ - uint64_t pageDirIndex = PAGE_DIR_GET_INDEX((uint64_t)addr); - kernelHeapDir[pageDirIndex] = 0; - addr = (void*)((uint64_t)addr + 0x200000); - } - } - - void Free4KPages(void* addr, uint64_t amount, address_space_t* addressSpace){ - uint64_t pml4Index, pdptIndex, pageDirIndex, pageIndex; - - uint64_t virt = (uint64_t)addr; - - while(amount--){ - pml4Index = PML4_GET_INDEX(virt); - pdptIndex = PDPT_GET_INDEX(virt); - pageDirIndex = PAGE_DIR_GET_INDEX(virt); - pageIndex = PAGE_TABLE_GET_INDEX(virt); - - const char* panic[1] = {"Process address space cannot be >512GB"}; - if(pdptIndex > MAX_PDPT_INDEX || pml4Index) KernelPanic(panic,1); - - if(!(addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1)) continue; - - addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex] = 0; - - invlpg(virt); - - virt += PAGE_SIZE_4K; /* Go to next page */ - } - } - - void KernelMapVirtualMemory2M(uint64_t phys, uint64_t virt, uint64_t amount){ - uint64_t pageDirIndex = PAGE_DIR_GET_INDEX(virt); - - while(amount--){ - kernelHeapDir[pageDirIndex] = 0x83; - SetPageFrame(&(kernelHeapDir[pageDirIndex]), phys); - kernelHeapDir[pageDirIndex] |= 0x83; - pageDirIndex++; - phys += PAGE_SIZE_2M; - } - } - - void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, uint64_t flags){ - uint64_t pageDirIndex, pageIndex; - - while(amount--){ - pageDirIndex = PAGE_DIR_GET_INDEX(virt); - pageIndex = PAGE_TABLE_GET_INDEX(virt); - SetPageFrame(&(kernelHeapDirTables[pageDirIndex][pageIndex]), phys); - kernelHeapDirTables[pageDirIndex][pageIndex] |= flags; - invlpg(virt); - phys += PAGE_SIZE_4K; - virt += PAGE_SIZE_4K; - } - } - - void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount){ - KernelMapVirtualMemory4K(phys, virt, amount, PAGE_WRITABLE | PAGE_PRESENT); - } - - void MapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, address_space_t* addressSpace){ - uint64_t pml4Index, pdptIndex, pageDirIndex, pageIndex; - - //phys &= ~(PAGE_SIZE_4K-1); - //virt &= ~(PAGE_SIZE_4K-1); - - while(amount--){ - pml4Index = PML4_GET_INDEX(virt); - pdptIndex = PDPT_GET_INDEX(virt); - pageDirIndex = PAGE_DIR_GET_INDEX(virt); - pageIndex = PAGE_TABLE_GET_INDEX(virt); - - const char* panic[1] = {"Process address space cannot be >512GB"}; - if(pdptIndex > MAX_PDPT_INDEX || pml4Index) KernelPanic(panic,1); - - if(!(addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1)) CreatePageTable(pdptIndex,pageDirIndex,addressSpace); // If we don't have a page table at this address, create one. - - addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex] = PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; - SetPageFrame(&(addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex]), phys); - - invlpg(virt); - - phys += PAGE_SIZE_4K; - virt += PAGE_SIZE_4K; /* Go to next page */ - } - } - - uintptr_t GetIOMapping(uintptr_t addr){ - if(addr > 0xffffffff){ // Typically most MMIO will not reside > 4GB, but check just in case - Log::Error("MMIO >4GB current unsupported"); - return 0xffffffff; - } - - return addr + IO_VIRTUAL_BASE; - } - - void ChangeAddressSpace(address_space_t* addressSpace){ - currentAddressSpace = addressSpace; - } - - void PageFaultHandler(void*, regs64_t* regs) - { - asm("cli"); - write_serial_n("Page Fault\r\n", 12); - Log::SetVideoConsole(nullptr); - - int err_code = IDT::GetErrCode(); - - uint64_t faultAddress; - asm volatile("movq %%cr2, %0" : "=r" (faultAddress)); - - int present = !(err_code & 0x1); // Page not present - int rw = err_code & 0x2; // Attempted write to read only page - int us = err_code & 0x4; // Processor was in user-mode and tried to access kernel page - int reserved = err_code & 0x8; // Overwritten CPU-reserved bits of page entry - int id = err_code & 0x10; // Caused by an instruction fetch - - if (present) - Log::Info("Page not present"); // Print fault to serial - if (rw) - Log::Info("Read Only"); - if (us) - Log::Info("User mode process tried to access kernel memory"); - if (reserved) - Log::Info("Reserved"); - if (id) - Log::Info("instruction fetch"); - - Log::Info("RIP:"); - - Log::Info(regs->rip); - - Log::Info("Process:"); - Log::Info(Scheduler::GetCurrentProcess()->pid); - - Log::Info("\r\nFault address: "); - Log::Info(faultAddress); - - Log::Info("Register Dump: a: "); - Log::Write(regs->rax); - Log::Write(", b:"); - Log::Write(regs->rbx); - Log::Write(", c:"); - Log::Write(regs->rcx); - Log::Write(", d:"); - Log::Write(regs->rdx); - Log::Write(", S:"); - Log::Write(regs->rsi); - Log::Write(", D:"); - Log::Write(regs->rdi); - Log::Write(", sp:"); - Log::Write(regs->rsp); - Log::Write(", bp:"); - Log::Write(regs->rbp); - - if((regs->ss & 0x3)){ - Log::Warning("Process %s crashed, PID: ", Scheduler::GetCurrentProcess()->name); - Log::Write(Scheduler::GetCurrentProcess()->pid); - Log::Write(", RIP: "); - Log::Write(regs->rip); - Log::Info("Stack trace:"); - UserPrintStackTrace(regs->rbp, Scheduler::GetCurrentProcess()->addressSpace); - Scheduler::EndProcess(Scheduler::GetCurrentProcess()); - return; - }; - - // Kernel Panic so tell other processors to stop executing - APIC::Local::SendIPI(0, ICR_DSH_OTHER /* Send to all other processors except us */, ICR_MESSAGE_TYPE_FIXED, IPI_HALT); - - Log::Info("Last syscall: %d", lastSyscall); - - PrintStackTrace(regs->rbp); - - char temp[16]; - char temp2[16]; - char temp3[16]; - const char* reasons[]{"Page Fault","RIP: ", itoa(regs->rip, temp, 16),"Address: ",itoa(faultAddress, temp2, 16), "Process:", itoa(Scheduler::GetCurrentProcess()->pid,temp3,10)};; - KernelPanic(reasons,7); - for (;;); - } +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//extern uint32_t kernel_end; + +#define KERNEL_HEAP_PDPT_INDEX 511 +#define KERNEL_HEAP_PML4_INDEX 511 + +address_space_t* currentAddressSpace; + +uint64_t kernelPML4Phys; +extern int lastSyscall; + +namespace Memory{ + pml4_t kernelPML4 __attribute__((aligned(4096))); + pdpt_t kernelPDPT __attribute__((aligned(4096))); // Kernel itself will reside here (0xFFFFFFFF80000000) + page_dir_t kernelDir __attribute__((aligned(4096))); + page_dir_t kernelHeapDir __attribute__((aligned(4096))); + page_t kernelHeapDirTables[TABLES_PER_DIR][PAGES_PER_TABLE] __attribute__((aligned(4096))); + page_dir_t ioDirs[4] __attribute__((aligned(4096))); + + uint64_t VirtualToPhysicalAddress(uint64_t addr) { + uint64_t address = 0; + + uint32_t pml4Index = PML4_GET_INDEX(addr); + uint32_t pageDirIndex = PAGE_DIR_GET_INDEX(addr); + uint32_t pageTableIndex = PAGE_TABLE_GET_INDEX(addr); + + if(pml4Index < 511){ // From Process Address Space + + } else { // From Kernel Address Space + if(kernelHeapDir[pageDirIndex] & 0x80){ + address = (GetPageFrame(kernelHeapDir[pageDirIndex])) << 12; + } else { + address = (GetPageFrame(kernelHeapDirTables[pageDirIndex][pageTableIndex])) << 12; + } + } + return address; + } + + uint64_t VirtualToPhysicalAddress(uint64_t addr, address_space_t* addressSpace) { + uint64_t address = 0; + + uint32_t pml4Index = PML4_GET_INDEX(addr); + uint32_t pdptIndex = PDPT_GET_INDEX(addr); + uint32_t pageDirIndex = PAGE_DIR_GET_INDEX(addr); + uint32_t pageTableIndex = PAGE_TABLE_GET_INDEX(addr); + + if(pml4Index == 0){ // From Process Address Space + if((addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1) && addressSpace->pageTables[pdptIndex][pageDirIndex]) + return addressSpace->pageTables[pdptIndex][pageDirIndex][pageTableIndex] & PAGE_FRAME; + else return 0; + } else { // From Kernel Address Space + if(kernelHeapDir[pageDirIndex] & 0x80){ + address = (GetPageFrame(kernelHeapDir[pageDirIndex])) << 12; + } else { + address = (GetPageFrame(kernelHeapDirTables[pageDirIndex][pageTableIndex])) << 12; + } + } + return address; + } + + void InitializeVirtualMemory() + { + IDT::RegisterInterruptHandler(14,PageFaultHandler); + memset(kernelPML4, 0, sizeof(pml4_t)); + memset(kernelPDPT, 0, sizeof(pdpt_t)); + memset(kernelHeapDir, 0, sizeof(page_dir_t)); + + SetPageFrame(&(kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)]),((uint64_t)kernelPDPT - KERNEL_VIRTUAL_BASE)); + kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)] |= 0x3; + kernelPML4[0] = kernelPML4[PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)]; + + kernelPDPT[PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)] = ((uint64_t)kernelDir - KERNEL_VIRTUAL_BASE) | 0x3; + for(int j = 0; j < TABLES_PER_DIR; j++){ + kernelDir[j] = (PAGE_SIZE_2M * j) | 0x83; + } + + kernelPDPT[KERNEL_HEAP_PDPT_INDEX] = 0x3; + SetPageFrame(&(kernelPDPT[KERNEL_HEAP_PDPT_INDEX]), (uint64_t)kernelHeapDir - KERNEL_VIRTUAL_BASE); + + for(int i = 0; i < 4; i++){ + kernelPDPT[PDPT_GET_INDEX(IO_VIRTUAL_BASE) + i] = ((uint64_t)ioDirs[i] - KERNEL_VIRTUAL_BASE) | 0x3;//(PAGE_SIZE_1G * i) | 0x83; + for(int j = 0; j < TABLES_PER_DIR; j++){ + ioDirs[i][j] = (PAGE_SIZE_1G * i + PAGE_SIZE_2M * j) | (PDE_2M | PDE_WRITABLE | PDE_PRESENT | PDE_CACHE_DISABLED); + } + } + + kernelPDPT[0] = kernelPDPT[PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)]; // Its important that we identity map low memory for SMP + + for(int i = 0; i < TABLES_PER_DIR; i++){ + memset(&(kernelHeapDirTables[i]),0,sizeof(page_t)*PAGES_PER_TABLE); + } + + kernelPML4Phys = (uint64_t)kernelPML4 - KERNEL_VIRTUAL_BASE; + asm("mov %%rax, %%cr3" :: "a"((uint64_t)kernelPML4 - KERNEL_VIRTUAL_BASE)); + } + + address_space_t* CreateAddressSpace(){ + address_space_t* addressSpace = (address_space_t*)kmalloc(sizeof(address_space_t)); + + pdpt_entry_t* pdpt = (pdpt_entry_t*)Memory::KernelAllocate4KPages(1); // PDPT; + uintptr_t pdptPhys = Memory::AllocatePhysicalMemoryBlock(); + Memory::KernelMapVirtualMemory4K(pdptPhys, (uintptr_t)pdpt,1); + memset((pdpt_entry_t*)pdpt,0,4096); + + pd_entry_t** pageDirs = (pd_entry_t**)KernelAllocate4KPages(1); // Page Dirs + Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageDirs,1); + uint64_t* pageDirsPhys = (uint64_t*)KernelAllocate4KPages(1); // Page Dirs + Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageDirsPhys,1); + page_t*** pageTables = (page_t***)KernelAllocate4KPages(1); // Page Tables + Memory::KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(), (uintptr_t)pageTables,1); + + pml4_entry_t* pml4 = (pml4_entry_t*)KernelAllocate4KPages(1); // Page Tables + uintptr_t pml4Phys = Memory::AllocatePhysicalMemoryBlock(); + Memory::KernelMapVirtualMemory4K(pml4Phys, (uintptr_t)pml4,1); + memcpy(pml4, kernelPML4, 4096); + + for(int i = 0; i < 512; i++){ + pageDirs[i] = (pd_entry_t*)KernelAllocate4KPages(1); + pageDirsPhys[i] = Memory::AllocatePhysicalMemoryBlock(); + KernelMapVirtualMemory4K(pageDirsPhys[i],(uintptr_t)pageDirs[i],1); + + pageTables[i] = (page_t**)Memory::KernelAllocate4KPages(1); + KernelMapVirtualMemory4K(Memory::AllocatePhysicalMemoryBlock(),(uintptr_t)pageTables[i],1); + + SetPageFrame(&(pdpt[i]),pageDirsPhys[i]); + pdpt[i] |= PDPT_WRITABLE | PDPT_PRESENT | PDPT_USER; + + memset(pageDirs[i],0,4096); + memset(pageTables[i],0,4096); + } + + addressSpace->pageDirs = pageDirs; + addressSpace->pageDirsPhys = pageDirsPhys; + addressSpace->pageTables = pageTables; + addressSpace->pml4 = pml4; + addressSpace->pdptPhys = pdptPhys; + addressSpace->pml4Phys = pml4Phys; + addressSpace->pdpt = pdpt; + + pml4[0] = pdptPhys | PML4_PRESENT | PML4_WRITABLE | PAGE_USER; + + return addressSpace; + } + + void DestroyAddressSpace(address_space_t* addressSpace){ + for(int i = 0; i < DIRS_PER_PDPT; i++){ + for(int j = 0; j < TABLES_PER_DIR; j++){ + pd_entry_t dirEnt = addressSpace->pageDirs[i][j]; + if(dirEnt & PAGE_PRESENT){ + uint64_t phys = GetPageFrame(dirEnt); + + for(int k = 0; k < PAGES_PER_TABLE; k++){ + if(addressSpace->pageTables[i][j][k] & 0x1){ + uint64_t pagePhys = GetPageFrame(addressSpace->pageTables[i][j][k]); + FreePhysicalMemoryBlock(pagePhys); + } + } + + FreePhysicalMemoryBlock(phys); + addressSpace->pageDirs[i][j] = 0; + KernelFree4KPages(addressSpace->pageTables[i][j], 1); + } + addressSpace->pageDirs[i][j] = 0; + } + + addressSpace->pdpt[i] = 0; + Memory::FreePhysicalMemoryBlock(addressSpace->pageDirsPhys[i]); + KernelFree4KPages(addressSpace->pageDirs[i], 1); + } + } + + bool CheckRegion(uintptr_t addr, uint64_t len, address_space_t* addressSpace){ + return addr < PDPT_SIZE && (addr + len) < PDPT_SIZE && (addressSpace->pdpt[PDPT_GET_INDEX(addr)] & PDPT_USER) && (addressSpace->pdpt[PDPT_GET_INDEX(addr + len)] & PDPT_USER); + } + + bool CheckKernelPointer(uintptr_t addr, uint64_t len){ + if(PML4_GET_INDEX(addr) != PML4_GET_INDEX(KERNEL_VIRTUAL_BASE)){ + return 0; + } + + if(!(kernelPDPT[PDPT_GET_INDEX(addr)] & 0x1)){ + return 0; + } + + if(PDPT_GET_INDEX(addr) == KERNEL_HEAP_PDPT_INDEX){ + if(!(kernelHeapDir[PAGE_DIR_GET_INDEX(addr)] & 0x1)){ + return 0; + } + + if(!(kernelHeapDir[PAGE_DIR_GET_INDEX(addr)] & PDE_2M)){ + if(!(kernelHeapDirTables[PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & 0x1)){ + return 0; + } + } + } else if(PDPT_GET_INDEX(addr) == PDPT_GET_INDEX(KERNEL_VIRTUAL_BASE)){ + if(!(kernelDir[PAGE_DIR_GET_INDEX(addr)] & 0x1)){ + return 0; + } + } else { + return 0; + } + + return 1; + } + + bool CheckUsermodePointer(uintptr_t addr, uint64_t len, address_space_t* addressSpace){ + if(addr >> 48) return 0; // Non-canonical or higher-half address + + if(!(addressSpace->pageDirs[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)] & (PAGE_PRESENT))){ + return 0; + } + + if(!(addressSpace->pageDirs[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)] & (PAGE_PRESENT))){ + return 0; + } + + if(!((addressSpace->pageTables[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & (PAGE_PRESENT)) && addressSpace->pageTables[PDPT_GET_INDEX(addr)][PAGE_DIR_GET_INDEX(addr)][PAGE_TABLE_GET_INDEX(addr)] & (PAGE_USER))){ + return 0; + } + + if(!((addressSpace->pageTables[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)][PAGE_TABLE_GET_INDEX(addr + len)] & (PAGE_PRESENT)) && addressSpace->pageTables[PDPT_GET_INDEX(addr + len)][PAGE_DIR_GET_INDEX(addr + len)][PAGE_TABLE_GET_INDEX(addr + len)] & (PAGE_USER))){ + return 0; + } + + return 1; + } + + page_table_t AllocatePageTable(){ + void* virt = KernelAllocate4KPages(1); + uint64_t phys = Memory::AllocatePhysicalMemoryBlock(); + + KernelMapVirtualMemory4K(phys,(uintptr_t)virt, 1); + + page_table_t pTable; + pTable.phys = phys; + pTable.virt = (page_t*)virt; + + for(int i = 0; i < PAGES_PER_TABLE; i++){ + ((page_t*)virt)[i] = 0; + } + + return pTable; + } + + void CreatePageTable(uint16_t pdptIndex, uint16_t pageDirIndex, address_space_t* addressSpace){ + page_table_t pTable = AllocatePageTable(); + SetPageFrame(&(addressSpace->pageDirs[pdptIndex][pageDirIndex]),pTable.phys); + addressSpace->pageDirs[pdptIndex][pageDirIndex] |= PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; + addressSpace->pageTables[pdptIndex][pageDirIndex] = pTable.virt; + } + + void* Allocate4KPages(uint64_t amount, address_space_t* addressSpace){ + uint64_t offset = 0; + uint64_t pageDirOffset = 0; + uint64_t counter = 0; + uintptr_t address = 0; + + uint64_t pml4Index = 0; + for(int d = 0; d < 512; d++){ + uint64_t pdptIndex = d; + if(!(addressSpace->pdpt[d] & 0x1)) break; + /* Attempt 1: Already Allocated Page Tables*/ + for(int i = 0; i < TABLES_PER_DIR; i++){ + if(addressSpace->pageDirs[d][i] & 0x1 && !(addressSpace->pageDirs[d][i] & 0x80)){ + for(int j = 0; j < PAGES_PER_TABLE; j++){ + if(addressSpace->pageTables[d][i][j] & 0x1){ + pageDirOffset = i; + offset = j+1; + counter = 0; + continue; + } + + counter++; + + if(counter >= amount){ + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); + while(counter--){ + if(offset >= 512){ + pageDirOffset++; + offset = 0; + } + addressSpace->pageTables[d][pageDirOffset][offset] = 0x3; + offset++; + } + + return (void*)address; + } + } + } else { + pageDirOffset = i+1; + offset = 0; + counter = 0; + } + } + + pageDirOffset = 0; + offset = 0; + counter = 0; + + /* Attempt 2: Allocate Page Tables*/ + for(int i = 0; i < TABLES_PER_DIR; i++){ + if(!(addressSpace->pageDirs[d][i] & 0x1)){ + + CreatePageTable(d,i,addressSpace); + for(int j = 0; j < PAGES_PER_TABLE; j++){ + + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); + counter++; + + if(counter >= amount){ + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); + while(counter--){ + if(offset >= 512){ + pageDirOffset ++; + offset = 0; + } + addressSpace->pageTables[d][pageDirOffset][offset] = 0x3; + offset++; + } + return (void*)address; + } + } + } else { + pageDirOffset = i+1; + offset = 0; + counter = 0; + } + } + Log::Info("new dir"); + } + + const char* reasons[1] = {"Out of Virtual Memory!"}; + KernelPanic(reasons, 1); + } + + void* KernelAllocate4KPages(uint64_t amount){ + uint64_t offset = 0; + uint64_t pageDirOffset = 0; + uint64_t counter = 0; + uintptr_t address = 0; + + uint64_t pml4Index = KERNEL_HEAP_PML4_INDEX; + uint64_t pdptIndex = KERNEL_HEAP_PDPT_INDEX; + + /* Attempt 1: Already Allocated Page Tables*/ + for(int i = 0; i < TABLES_PER_DIR; i++){ + if(kernelHeapDir[i] & 0x1 && !(kernelHeapDir[i] & 0x80)){ + for(int j = 0; j < TABLES_PER_DIR; j++){ + if(kernelHeapDirTables[i][j] & 0x1){ + pageDirOffset = i; + offset = j+1; + counter = 0; + continue; + } + + counter++; + + if(counter >= amount){ + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); + address |= 0xFFFF000000000000; + while(counter--){ + if(offset >= 512){ + pageDirOffset++; + offset = 0; + } + kernelHeapDirTables[pageDirOffset][offset] = 0x3; + offset++; + } + + return (void*)address; + } + } + } else { + pageDirOffset = i+1; + offset = 0; + counter = 0; + } + } + + pageDirOffset = 0; + offset = 0; + counter = 0; + + /* Attempt 2: Allocate Page Tables*/ + for(int i = 0; i < TABLES_PER_DIR; i++){ + if(!(kernelHeapDir[i] & 0x1)){ + counter += 512; + + if(counter >= amount){ + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + (pageDirOffset * PAGE_SIZE_2M) + (offset*PAGE_SIZE_4K); + address |= 0xFFFF000000000000; + //kernelHeapDir[i] = (PAGE_FRAME & ((uintptr_t)&(kernelHeapDirTables[i]) - KERNEL_VIRTUAL_BASE)) | 0x3; + SetPageFrame(&(kernelHeapDir[pageDirOffset]),((uintptr_t)&(kernelHeapDirTables[pageDirOffset]) - KERNEL_VIRTUAL_BASE)); + kernelHeapDir[pageDirOffset] |= 0x3; + while(amount--){ + if(offset >= 512){ + pageDirOffset ++; + offset = 0; + SetPageFrame(&(kernelHeapDir[pageDirOffset]),((uintptr_t)&(kernelHeapDirTables[pageDirOffset]) - KERNEL_VIRTUAL_BASE)); + kernelHeapDir[pageDirOffset] |= 0x3; + } + kernelHeapDirTables[pageDirOffset][offset] = 0x3; + offset++; + } + return (void*)address; + } + } else { + pageDirOffset = i+1; + offset = 0; + counter = 0; + } + } + + Log::Error("Kernel Out of Virtual Memory"); + const char* reasons[1] = {"Kernel Out of Virtual Memory!"}; + KernelPanic(reasons, 1); + } + + void* KernelAllocate2MPages(uint64_t amount){ + uint64_t address = 0; + uint64_t offset = 0; + uint64_t counter = 0; + uint64_t pdptIndex = KERNEL_HEAP_PDPT_INDEX; + uint64_t pml4Index = KERNEL_HEAP_PML4_INDEX; + + for(int i = 0; i < TABLES_PER_DIR; i++){ + if(kernelHeapDir[i] & 0x1){ + offset = i+1; + counter = 0; + continue; + } + counter++; + + if(counter >= amount){ + address = (PDPT_SIZE * pml4Index) + (pdptIndex * PAGE_SIZE_1G) + offset * PAGE_SIZE_2M; + address |= 0xFFFF000000000000; + while(counter--){ + kernelHeapDir[offset] = 0x83; + offset++; + } + return (void*)address; + } + } + + Log::Error("Kernel Out of Virtual Memory"); + const char* reasons[1] = {"Kernel Out of Virtual Memory!"}; + KernelPanic(reasons, 1); + for(;;); + } + + void KernelFree4KPages(void* addr, uint64_t amount){ + uint64_t pageDirIndex, pageIndex; + uint64_t virt = (uint64_t)addr; + + while(amount--){ + pageDirIndex = PAGE_DIR_GET_INDEX(virt); + pageIndex = PAGE_TABLE_GET_INDEX(virt); + kernelHeapDirTables[pageDirIndex][pageIndex] = 0; + invlpg(virt); + virt += PAGE_SIZE_4K; + } + } + + void KernelFree2MPages(void* addr, uint64_t amount){ + while(amount--){ + uint64_t pageDirIndex = PAGE_DIR_GET_INDEX((uint64_t)addr); + kernelHeapDir[pageDirIndex] = 0; + addr = (void*)((uint64_t)addr + 0x200000); + } + } + + void Free4KPages(void* addr, uint64_t amount, address_space_t* addressSpace){ + uint64_t pml4Index, pdptIndex, pageDirIndex, pageIndex; + + uint64_t virt = (uint64_t)addr; + + while(amount--){ + pml4Index = PML4_GET_INDEX(virt); + pdptIndex = PDPT_GET_INDEX(virt); + pageDirIndex = PAGE_DIR_GET_INDEX(virt); + pageIndex = PAGE_TABLE_GET_INDEX(virt); + + const char* panic[1] = {"Process address space cannot be >512GB"}; + if(pdptIndex > MAX_PDPT_INDEX || pml4Index) KernelPanic(panic,1); + + if(!(addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1)) continue; + + addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex] = 0; + + invlpg(virt); + + virt += PAGE_SIZE_4K; /* Go to next page */ + } + } + + void KernelMapVirtualMemory2M(uint64_t phys, uint64_t virt, uint64_t amount){ + uint64_t pageDirIndex = PAGE_DIR_GET_INDEX(virt); + + while(amount--){ + kernelHeapDir[pageDirIndex] = 0x83; + SetPageFrame(&(kernelHeapDir[pageDirIndex]), phys); + kernelHeapDir[pageDirIndex] |= 0x83; + pageDirIndex++; + phys += PAGE_SIZE_2M; + } + } + + void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, uint64_t flags){ + uint64_t pageDirIndex, pageIndex; + + while(amount--){ + pageDirIndex = PAGE_DIR_GET_INDEX(virt); + pageIndex = PAGE_TABLE_GET_INDEX(virt); + SetPageFrame(&(kernelHeapDirTables[pageDirIndex][pageIndex]), phys); + kernelHeapDirTables[pageDirIndex][pageIndex] |= flags; + invlpg(virt); + phys += PAGE_SIZE_4K; + virt += PAGE_SIZE_4K; + } + } + + void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount){ + KernelMapVirtualMemory4K(phys, virt, amount, PAGE_WRITABLE | PAGE_PRESENT); + } + + void MapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, address_space_t* addressSpace){ + uint64_t pml4Index, pdptIndex, pageDirIndex, pageIndex; + + //phys &= ~(PAGE_SIZE_4K-1); + //virt &= ~(PAGE_SIZE_4K-1); + + while(amount--){ + pml4Index = PML4_GET_INDEX(virt); + pdptIndex = PDPT_GET_INDEX(virt); + pageDirIndex = PAGE_DIR_GET_INDEX(virt); + pageIndex = PAGE_TABLE_GET_INDEX(virt); + + const char* panic[1] = {"Process address space cannot be >512GB"}; + if(pdptIndex > MAX_PDPT_INDEX || pml4Index) KernelPanic(panic,1); + + if(!(addressSpace->pageDirs[pdptIndex][pageDirIndex] & 0x1)) CreatePageTable(pdptIndex,pageDirIndex,addressSpace); // If we don't have a page table at this address, create one. + + addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex] = PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; + SetPageFrame(&(addressSpace->pageTables[pdptIndex][pageDirIndex][pageIndex]), phys); + + invlpg(virt); + + phys += PAGE_SIZE_4K; + virt += PAGE_SIZE_4K; /* Go to next page */ + } + } + + uintptr_t GetIOMapping(uintptr_t addr){ + if(addr > 0xffffffff){ // Typically most MMIO will not reside > 4GB, but check just in case + Log::Error("MMIO >4GB current unsupported"); + return 0xffffffff; + } + + return addr + IO_VIRTUAL_BASE; + } + + void ChangeAddressSpace(address_space_t* addressSpace){ + currentAddressSpace = addressSpace; + } + + void PageFaultHandler(void*, regs64_t* regs) + { + asm("cli"); + write_serial_n("Page Fault\r\n", 12); + Log::SetVideoConsole(nullptr); + + int err_code = IDT::GetErrCode(); + + uint64_t faultAddress; + asm volatile("movq %%cr2, %0" : "=r" (faultAddress)); + + int present = !(err_code & 0x1); // Page not present + int rw = err_code & 0x2; // Attempted write to read only page + int us = err_code & 0x4; // Processor was in user-mode and tried to access kernel page + int reserved = err_code & 0x8; // Overwritten CPU-reserved bits of page entry + int id = err_code & 0x10; // Caused by an instruction fetch + + if (present) + Log::Info("Page not present"); // Print fault to serial + if (rw) + Log::Info("Read Only"); + if (us) + Log::Info("User mode process tried to access kernel memory"); + if (reserved) + Log::Info("Reserved"); + if (id) + Log::Info("instruction fetch"); + + Log::Info("RIP:"); + + Log::Info(regs->rip); + + Log::Info("Process:"); + Log::Info(Scheduler::GetCurrentProcess()->pid); + + Log::Info("\r\nFault address: "); + Log::Info(faultAddress); + + Log::Info("Register Dump: a: "); + Log::Write(regs->rax); + Log::Write(", b:"); + Log::Write(regs->rbx); + Log::Write(", c:"); + Log::Write(regs->rcx); + Log::Write(", d:"); + Log::Write(regs->rdx); + Log::Write(", S:"); + Log::Write(regs->rsi); + Log::Write(", D:"); + Log::Write(regs->rdi); + Log::Write(", sp:"); + Log::Write(regs->rsp); + Log::Write(", bp:"); + Log::Write(regs->rbp); + + if((regs->ss & 0x3)){ + Log::Warning("Process %s crashed, PID: ", Scheduler::GetCurrentProcess()->name); + Log::Write(Scheduler::GetCurrentProcess()->pid); + Log::Write(", RIP: "); + Log::Write(regs->rip); + Log::Info("Stack trace:"); + UserPrintStackTrace(regs->rbp, Scheduler::GetCurrentProcess()->addressSpace); + Scheduler::EndProcess(Scheduler::GetCurrentProcess()); + return; + }; + + // Kernel Panic so tell other processors to stop executing + APIC::Local::SendIPI(0, ICR_DSH_OTHER /* Send to all other processors except us */, ICR_MESSAGE_TYPE_FIXED, IPI_HALT); + + Log::Info("Last syscall: %d", lastSyscall); + + PrintStackTrace(regs->rbp); + + char temp[16]; + char temp2[16]; + char temp3[16]; + const char* reasons[]{"Page Fault","RIP: ", itoa(regs->rip, temp, 16),"Address: ",itoa(faultAddress, temp2, 16), "Process:", itoa(Scheduler::GetCurrentProcess()->pid,temp3,10)};; + KernelPanic(reasons,7); + for (;;); + } } \ No newline at end of file diff --git a/Kernel/src/arch/x86_64/smptrampoline.asm b/Kernel/src/arch/x86_64/smptrampoline.asm index 233fe500..3cc80df9 100755 --- a/Kernel/src/arch/x86_64/smptrampoline.asm +++ b/Kernel/src/arch/x86_64/smptrampoline.asm @@ -1,60 +1,60 @@ -BITS 16 - -%include "smpdefines.inc" - -cli -cld - -mov ax, SMP_MAGIC -mov word [SMP_TRAMPOLINE_DATA_START_FLAG], ax - -mov eax, cr4 -or eax, 1 << 5 ; Set PAE bit -mov cr4, eax - -mov eax, dword [SMP_TRAMPOLINE_CR3] -mov cr3, eax - -mov ecx, 0xC0000080 ; EFER Model Specific Register -rdmsr ; Read from the MSR -or eax, 1 << 8 -wrmsr - -mov eax, cr0 -or eax, 0x80000001 ; Paging, Protected Mode -mov cr0, eax - -lgdt [SMP_TRAMPOLINE_GDT_PTR] - -jmp 0x08:(smpentry64 + SMP_TRAMPOLINE_ENTRY) - -hlt - -BITS 64 - -smpentry64: - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - - mov rsp, [SMP_TRAMPOLINE_STACK] - - mov rax, cr0 - and ax, 0xFFFB ; Clear coprocessor emulation - or ax, 0x2 ; Set coprocessor monitoring - mov cr0, rax - - ;Enable SSE - mov rax, cr4 - or ax, 3 << 9 ; Set flags for SSE - mov cr4, rax - - xor rbp, rbp - mov rdi, [SMP_TRAMPOLINE_CPU_ID] - call [SMP_TRAMPOLINE_ENTRY2] - - cli +BITS 16 + +%include "smpdefines.inc" + +cli +cld + +mov ax, SMP_MAGIC +mov word [SMP_TRAMPOLINE_DATA_START_FLAG], ax + +mov eax, cr4 +or eax, 1 << 5 ; Set PAE bit +mov cr4, eax + +mov eax, dword [SMP_TRAMPOLINE_CR3] +mov cr3, eax + +mov ecx, 0xC0000080 ; EFER Model Specific Register +rdmsr ; Read from the MSR +or eax, 1 << 8 +wrmsr + +mov eax, cr0 +or eax, 0x80000001 ; Paging, Protected Mode +mov cr0, eax + +lgdt [SMP_TRAMPOLINE_GDT_PTR] + +jmp 0x08:(smpentry64 + SMP_TRAMPOLINE_ENTRY) + +hlt + +BITS 64 + +smpentry64: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + mov rsp, [SMP_TRAMPOLINE_STACK] + + mov rax, cr0 + and ax, 0xFFFB ; Clear coprocessor emulation + or ax, 0x2 ; Set coprocessor monitoring + mov cr0, rax + + ;Enable SSE + mov rax, cr4 + or ax, 3 << 9 ; Set flags for SSE + mov cr4, rax + + xor rbp, rbp + mov rdi, [SMP_TRAMPOLINE_CPU_ID] + call [SMP_TRAMPOLINE_ENTRY2] + + cli hlt \ No newline at end of file diff --git a/Kernel/src/arch/x86_64/system.cpp b/Kernel/src/arch/x86_64/system.cpp index b803b19e..03c8878b 100755 --- a/Kernel/src/arch/x86_64/system.cpp +++ b/Kernel/src/arch/x86_64/system.cpp @@ -1,42 +1,42 @@ -#include -extern "C"{ -void outportb(uint16_t port, uint8_t value){ - asm volatile ("outb %1, %0" : : "dN" (port), "a" (value)); -} - -uint8_t inportb(uint16_t port){ - uint8_t value; - asm volatile("inb %1, %0" : "=a" (value) : "dN" (port)); - return value; -} - -void outportw(uint16_t port, uint16_t value){ - asm volatile ("outw %1, %0" : : "dN" (port), "a" (value)); -} - -uint16_t inportw(uint16_t port){ - uint16_t value; - asm volatile("inw %1, %0" : "=a" (value) : "dN" (port)); - return value; -} - -void outportd(uint16_t port, uint32_t value){ - asm volatile ("outl %1, %0" : : "dN" (port), "a" (value)); -} - -uint32_t inportd(uint16_t port){ - uint32_t value; - asm volatile("inl %1, %0" : "=a" (value) : "dN" (port)); - return value; -} - -void outportl(uint16_t port, uint32_t value){ - asm volatile ("outl %1, %0" : : "dN" (port), "a" (value)); -} - -uint32_t inportl(uint16_t port){ - uint32_t value; - asm volatile("inl %1, %0" : "=a" (value) : "dN" (port)); - return value; -} +#include +extern "C"{ +void outportb(uint16_t port, uint8_t value){ + asm volatile ("outb %1, %0" : : "dN" (port), "a" (value)); +} + +uint8_t inportb(uint16_t port){ + uint8_t value; + asm volatile("inb %1, %0" : "=a" (value) : "dN" (port)); + return value; +} + +void outportw(uint16_t port, uint16_t value){ + asm volatile ("outw %1, %0" : : "dN" (port), "a" (value)); +} + +uint16_t inportw(uint16_t port){ + uint16_t value; + asm volatile("inw %1, %0" : "=a" (value) : "dN" (port)); + return value; +} + +void outportd(uint16_t port, uint32_t value){ + asm volatile ("outl %1, %0" : : "dN" (port), "a" (value)); +} + +uint32_t inportd(uint16_t port){ + uint32_t value; + asm volatile("inl %1, %0" : "=a" (value) : "dN" (port)); + return value; +} + +void outportl(uint16_t port, uint32_t value){ + asm volatile ("outl %1, %0" : : "dN" (port), "a" (value)); +} + +uint32_t inportl(uint16_t port){ + uint32_t value; + asm volatile("inl %1, %0" : "=a" (value) : "dN" (port)); + return value; +} } \ No newline at end of file diff --git a/Kernel/src/fs/fat32.cpp b/Kernel/src/fs/fat32.cpp index 19f4cd1f..9fff0c8d 100755 --- a/Kernel/src/fs/fat32.cpp +++ b/Kernel/src/fs/fat32.cpp @@ -1,330 +1,330 @@ -#include - -#include -#include -#include -#include -#include - -namespace fs::FAT32{ - - int Identify(PartitionDevice* part){ - fat32_boot_record_t* bootRecord = (fat32_boot_record_t*)kmalloc(512); - - if(part->ReadBlock(0, 512, (uint8_t*)bootRecord)){ // Read Volume Boot Record (First sector of partition) - return -1; // Disk Error - } - - int isFat = 0; - - if(bootRecord->ebr.signature == 0x28 || bootRecord->ebr.signature == 0x29){ - uint32_t dataSectors = bootRecord->bpb.largeSectorCount - (bootRecord->bpb.reservedSectors + (bootRecord->ebr.sectorsPerFAT * bootRecord->bpb.fatCount)); - uint32_t clusters = dataSectors / bootRecord->bpb.sectorsPerCluster; - - if(clusters > 65525) isFat = 1; - } - - kfree(bootRecord); - - return isFat; - } - - uint64_t Fat32Volume::ClusterToLBA(uint32_t cluster){ - return (bootRecord->bpb.reservedSectors + bootRecord->bpb.fatCount * bootRecord->ebr.sectorsPerFAT) + cluster * bootRecord->bpb.sectorsPerCluster - (2 * bootRecord->bpb.sectorsPerCluster); - } - - Fat32Volume::Fat32Volume(PartitionDevice* _part, char* name){ - this->part = _part; - - fat32_boot_record_t* bootRecord = (fat32_boot_record_t*)kmalloc(512); - - if(part->ReadBlock(0, 512, (uint8_t*)bootRecord)){ // Read Volume Boot Record (First sector of partition) - Log::Warning("Disk Error Initializing Volume"); // Disk Error - return; - } - - this->bootRecord = bootRecord; - - Log::Info("[FAT32] Initializing Volume\tSignature: %d, OEM ID: %s, Size: %d MB", bootRecord->ebr.signature, (char*)bootRecord->bpb.oem, bootRecord->bpb.largeSectorCount * 512 / 1024 / 1024); - - clusterSizeBytes = bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize; - - fat32MountPoint.flags = FS_NODE_MOUNTPOINT | FS_NODE_DIRECTORY; - fat32MountPoint.inode = bootRecord->ebr.rootClusterNum; - - fat32MountPoint.vol = this; - fat32MountPoint.size = 0; - - mountPoint = &fat32MountPoint; - - mountPointDirent.flags = DT_DIR; - mountPointDirent.node = &fat32MountPoint; - strcpy(mountPointDirent.name, name); - - } - - List* Fat32Volume::GetClusterChain(uint32_t cluster){ - List* list = new List(); - - uint32_t* buf = (uint32_t*)kmalloc(4096); - - uint32_t lastBlock = 0xFFFFFFFF; - - do - { - list->add_back(cluster); - - uint32_t block = ((cluster * 4) / 4096); - uint32_t offset = cluster % (4096 / 4); - - if(block != lastBlock) { - if(part->ReadBlock(bootRecord->bpb.reservedSectors + block * (4096 / part->parentDisk->blocksize) /* Get Sector of Block */, 4096, buf)){ - delete list; - return nullptr; - } - - lastBlock = block; - } - - cluster = buf[offset] & 0x0FFFFFFF; - - } while(cluster && (cluster & 0x0FFFFFFF) < 0x0FFFFFF8); - - return list; - } - - void* Fat32Volume::ReadClusterChain(uint32_t cluster, int* clusterCount, size_t max){ - uint32_t maxCluster = (max / (bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize)) + 1; - List* clusterChain = GetClusterChain(cluster); - - if(!clusterChain) return nullptr; - - uint8_t* buf = reinterpret_cast(kmalloc(clusterChain->get_length() * clusterSizeBytes)); - void* _buf = buf; - - for(unsigned i = 0; i < clusterChain->get_length() && maxCluster; i++){ - part->ReadBlock(ClusterToLBA(clusterChain->get_at(i)), clusterSizeBytes, buf); - - buf += clusterSizeBytes; - } - - if(clusterCount) - *clusterCount = clusterChain->get_length(); - - delete clusterChain; - - return _buf; - } - - void* Fat32Volume::ReadClusterChain(uint32_t cluster, int* clusterCount){ - if(cluster == 0) cluster = bootRecord->ebr.rootClusterNum; - List* clusterChain = GetClusterChain(cluster); - - if(!clusterChain) return nullptr; - - uint8_t* buf = reinterpret_cast(kmalloc(clusterChain->get_length() * clusterSizeBytes)); - void* _buf = buf; - - for(unsigned i = 0; i < clusterChain->get_length(); i++){ - part->ReadBlock(ClusterToLBA(clusterChain->get_at(i)), clusterSizeBytes, buf); - - buf += clusterSizeBytes; - } - - if(clusterCount) - *clusterCount = clusterChain->get_length(); - - delete clusterChain; - - return _buf; - } - - ssize_t Fat32Volume::Read(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer){ - if(!node->inode || node->flags & FS_NODE_DIRECTORY) return -1; - - int count; - void* _buf = ReadClusterChain(node->inode, &count, size); - - if(static_cast(count) * bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize < size) return 0; - - memcpy(buffer, _buf, size); - return size; - } - - ssize_t Fat32Volume::Write(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer){ - return -EROFS; - - List* clusters = GetClusterChain(node->inode); - if(offset + size > clusters->get_length() * bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize){ - // TODO: Allocate clusters - Log::Info("[FAT32] Allocating Clusters"); - - } - } - - void Fat32Volume::Open(Fat32Node* node, uint32_t flags){ - - } - - void Fat32Volume::Close(Fat32Node* node){ - - } - - int Fat32Volume::ReadDir(Fat32Node* node, DirectoryEntry* dirent, uint32_t index){ - unsigned lfnCount = 0; - unsigned entryCount = 0; - - uint32_t cluster = node->inode; - int clusterCount = 0; - - fat_entry_t* dirEntries = (fat_entry_t*)ReadClusterChain(cluster, &clusterCount); - - fat_entry_t* dirEntry; - int dirEntryIndex = -1; - - fat_lfn_entry_t** lfnEntries; - - for(unsigned i = 0; i < static_cast(clusterCount) * clusterSizeBytes; i++){ - if(dirEntries[i].filename[0] == 0) continue; // No Directory Entry at index - else if (dirEntries[i].filename[0] == 0xE5) { - lfnCount = 0; - continue; // Unused Entry - } - else if (dirEntries[i].attributes == 0x0F) lfnCount++; // Long File Name Entry - else if (dirEntries[i].attributes & 0x08 /*Volume ID*/){ - lfnCount = 0; - continue; - } else { - if(entryCount == index){ - dirEntry = &dirEntries[i]; - dirEntryIndex = i; - break; - } - - entryCount++; - lfnCount = 0; - } - } - - if(dirEntryIndex == -1){ - return 0; - } - - lfnEntries = (fat_lfn_entry_t**)kmalloc(sizeof(fat_lfn_entry_t*) * lfnCount); - - for(unsigned i = 0; i < lfnCount; i++){ - fat_lfn_entry_t* lfnEntry = (fat_lfn_entry_t*)(&dirEntries[dirEntryIndex - i - 1]); - - lfnEntries[i] = lfnEntry; - } - - if(lfnCount){ - GetLongFilename(dirent->name, lfnEntries, lfnCount); - } else { - strncpy(dirent->name, (char*)dirEntry->filename, 8); - while(strchr(dirent->name, ' ')) *strchr(dirent->name, ' ') = 0; // Remove Spaces - if(strchr((char*)dirEntry->ext, ' ') != (char*)dirEntry->ext){ - strncpy(dirent->name + strlen(dirent->name), ".", 1); - strncpy(dirent->name + strlen(dirent->name), (char*)dirEntry->ext, 3); - } - } - - if(dirEntry->attributes & FAT_ATTR_DIRECTORY) dirent->flags = DT_DIR; - else dirent->flags = DT_REG; - - return 1; - } - - FsNode* Fat32Volume::FindDir(Fat32Node* node, char* name){ - unsigned lfnCount = 0; - - uint32_t cluster = node->inode; - int clusterCount = 0; - - fat_entry_t* dirEntries = (fat_entry_t*)ReadClusterChain(cluster, &clusterCount); - - List foundEntries; - List foundEntriesLfnCount; - - fat_lfn_entry_t** lfnEntries; - Fat32Node* _node = nullptr; - - for(unsigned i = 0; i < static_cast(clusterCount) * clusterSizeBytes; i++){ - if(dirEntries[i].filename[0] == 0) return nullptr; // No Directory Entry at index - else if (dirEntries[i].filename[0] == 0xE5) { - lfnCount = 0; - continue; // Unused Entry - } - else if (dirEntries[i].attributes == 0x0F) lfnCount++; // Long File Name Entry - else if (dirEntries[i].attributes & 0x08 /*Volume ID*/){ - lfnCount = 0; - continue; - } else { - char* _name = (char*)kmalloc(128); - if(lfnCount){ - lfnEntries = (fat_lfn_entry_t**)kmalloc(sizeof(fat_lfn_entry_t*) * lfnCount); - - for(unsigned k = 0; k < lfnCount; k++){ - fat_lfn_entry_t* lfnEntry = (fat_lfn_entry_t*)(&dirEntries[i - k - 1]); - - lfnEntries[k] = lfnEntry; - } - - GetLongFilename(_name, lfnEntries, lfnCount); - - kfree(lfnEntries); - } else { - strncpy(_name, (char*)dirEntries[i].filename, 8); - while(strchr(_name, ' ')) *strchr(_name, ' ') = 0; // Remove Spaces - if(strchr((char*)dirEntries[i].ext, ' ') != (char*)dirEntries[i].ext){ - strncpy(_name + strlen(_name), ".", 1); - strncpy(_name + strlen(_name), (char*)dirEntries[i].ext, 3); - } - } - - if(strcmp(_name, name) == 0){ - uint64_t clusterNum = (((uint32_t)dirEntries[i].highClusterNum) << 16) | dirEntries[i].lowClusterNum; - if(clusterNum == bootRecord->ebr.rootClusterNum || clusterNum == 0) - return mountPoint; // Root Directory - _node = new Fat32Node(); - _node->size = dirEntries[i].fileSize; - _node->inode = clusterNum; - if(dirEntries[i].attributes & FAT_ATTR_DIRECTORY) _node->flags = FS_NODE_DIRECTORY; - else _node->flags = FS_NODE_FILE; - break; - } - lfnCount = 0; - } - } - - if(_node){ - _node->vol = this; - } - - return _node; - } - - ssize_t Fat32Node::Read(size_t offset, size_t size, uint8_t *buffer){ - return vol->Read(this, offset, size, buffer); - } - - ssize_t Fat32Node::Write(size_t offset, size_t size, uint8_t *buffer){ - return vol->Write(this, offset, size, buffer); - } - - /*fs_fd_t* Fat32Node::Open(uint32_t flags){ - vol->Open(this, flags); - } - - void Fat32Node::Close(){ - vol->Close(this); - }*/ - - int Fat32Node::ReadDir(DirectoryEntry* dirent, uint32_t index){ - return vol->ReadDir(this, dirent, index); - } - - FsNode* Fat32Node::FindDir(char* name){ - return vol->FindDir(this, name); - } +#include + +#include +#include +#include +#include +#include + +namespace fs::FAT32{ + + int Identify(PartitionDevice* part){ + fat32_boot_record_t* bootRecord = (fat32_boot_record_t*)kmalloc(512); + + if(part->ReadBlock(0, 512, (uint8_t*)bootRecord)){ // Read Volume Boot Record (First sector of partition) + return -1; // Disk Error + } + + int isFat = 0; + + if(bootRecord->ebr.signature == 0x28 || bootRecord->ebr.signature == 0x29){ + uint32_t dataSectors = bootRecord->bpb.largeSectorCount - (bootRecord->bpb.reservedSectors + (bootRecord->ebr.sectorsPerFAT * bootRecord->bpb.fatCount)); + uint32_t clusters = dataSectors / bootRecord->bpb.sectorsPerCluster; + + if(clusters > 65525) isFat = 1; + } + + kfree(bootRecord); + + return isFat; + } + + uint64_t Fat32Volume::ClusterToLBA(uint32_t cluster){ + return (bootRecord->bpb.reservedSectors + bootRecord->bpb.fatCount * bootRecord->ebr.sectorsPerFAT) + cluster * bootRecord->bpb.sectorsPerCluster - (2 * bootRecord->bpb.sectorsPerCluster); + } + + Fat32Volume::Fat32Volume(PartitionDevice* _part, char* name){ + this->part = _part; + + fat32_boot_record_t* bootRecord = (fat32_boot_record_t*)kmalloc(512); + + if(part->ReadBlock(0, 512, (uint8_t*)bootRecord)){ // Read Volume Boot Record (First sector of partition) + Log::Warning("Disk Error Initializing Volume"); // Disk Error + return; + } + + this->bootRecord = bootRecord; + + Log::Info("[FAT32] Initializing Volume\tSignature: %d, OEM ID: %s, Size: %d MB", bootRecord->ebr.signature, (char*)bootRecord->bpb.oem, bootRecord->bpb.largeSectorCount * 512 / 1024 / 1024); + + clusterSizeBytes = bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize; + + fat32MountPoint.flags = FS_NODE_MOUNTPOINT | FS_NODE_DIRECTORY; + fat32MountPoint.inode = bootRecord->ebr.rootClusterNum; + + fat32MountPoint.vol = this; + fat32MountPoint.size = 0; + + mountPoint = &fat32MountPoint; + + mountPointDirent.flags = DT_DIR; + mountPointDirent.node = &fat32MountPoint; + strcpy(mountPointDirent.name, name); + + } + + List* Fat32Volume::GetClusterChain(uint32_t cluster){ + List* list = new List(); + + uint32_t* buf = (uint32_t*)kmalloc(4096); + + uint32_t lastBlock = 0xFFFFFFFF; + + do + { + list->add_back(cluster); + + uint32_t block = ((cluster * 4) / 4096); + uint32_t offset = cluster % (4096 / 4); + + if(block != lastBlock) { + if(part->ReadBlock(bootRecord->bpb.reservedSectors + block * (4096 / part->parentDisk->blocksize) /* Get Sector of Block */, 4096, buf)){ + delete list; + return nullptr; + } + + lastBlock = block; + } + + cluster = buf[offset] & 0x0FFFFFFF; + + } while(cluster && (cluster & 0x0FFFFFFF) < 0x0FFFFFF8); + + return list; + } + + void* Fat32Volume::ReadClusterChain(uint32_t cluster, int* clusterCount, size_t max){ + uint32_t maxCluster = (max / (bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize)) + 1; + List* clusterChain = GetClusterChain(cluster); + + if(!clusterChain) return nullptr; + + uint8_t* buf = reinterpret_cast(kmalloc(clusterChain->get_length() * clusterSizeBytes)); + void* _buf = buf; + + for(unsigned i = 0; i < clusterChain->get_length() && maxCluster; i++){ + part->ReadBlock(ClusterToLBA(clusterChain->get_at(i)), clusterSizeBytes, buf); + + buf += clusterSizeBytes; + } + + if(clusterCount) + *clusterCount = clusterChain->get_length(); + + delete clusterChain; + + return _buf; + } + + void* Fat32Volume::ReadClusterChain(uint32_t cluster, int* clusterCount){ + if(cluster == 0) cluster = bootRecord->ebr.rootClusterNum; + List* clusterChain = GetClusterChain(cluster); + + if(!clusterChain) return nullptr; + + uint8_t* buf = reinterpret_cast(kmalloc(clusterChain->get_length() * clusterSizeBytes)); + void* _buf = buf; + + for(unsigned i = 0; i < clusterChain->get_length(); i++){ + part->ReadBlock(ClusterToLBA(clusterChain->get_at(i)), clusterSizeBytes, buf); + + buf += clusterSizeBytes; + } + + if(clusterCount) + *clusterCount = clusterChain->get_length(); + + delete clusterChain; + + return _buf; + } + + ssize_t Fat32Volume::Read(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer){ + if(!node->inode || node->flags & FS_NODE_DIRECTORY) return -1; + + int count; + void* _buf = ReadClusterChain(node->inode, &count, size); + + if(static_cast(count) * bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize < size) return 0; + + memcpy(buffer, _buf, size); + return size; + } + + ssize_t Fat32Volume::Write(Fat32Node* node, size_t offset, size_t size, uint8_t *buffer){ + return -EROFS; + + List* clusters = GetClusterChain(node->inode); + if(offset + size > clusters->get_length() * bootRecord->bpb.sectorsPerCluster * part->parentDisk->blocksize){ + // TODO: Allocate clusters + Log::Info("[FAT32] Allocating Clusters"); + + } + } + + void Fat32Volume::Open(Fat32Node* node, uint32_t flags){ + + } + + void Fat32Volume::Close(Fat32Node* node){ + + } + + int Fat32Volume::ReadDir(Fat32Node* node, DirectoryEntry* dirent, uint32_t index){ + unsigned lfnCount = 0; + unsigned entryCount = 0; + + uint32_t cluster = node->inode; + int clusterCount = 0; + + fat_entry_t* dirEntries = (fat_entry_t*)ReadClusterChain(cluster, &clusterCount); + + fat_entry_t* dirEntry; + int dirEntryIndex = -1; + + fat_lfn_entry_t** lfnEntries; + + for(unsigned i = 0; i < static_cast(clusterCount) * clusterSizeBytes; i++){ + if(dirEntries[i].filename[0] == 0) continue; // No Directory Entry at index + else if (dirEntries[i].filename[0] == 0xE5) { + lfnCount = 0; + continue; // Unused Entry + } + else if (dirEntries[i].attributes == 0x0F) lfnCount++; // Long File Name Entry + else if (dirEntries[i].attributes & 0x08 /*Volume ID*/){ + lfnCount = 0; + continue; + } else { + if(entryCount == index){ + dirEntry = &dirEntries[i]; + dirEntryIndex = i; + break; + } + + entryCount++; + lfnCount = 0; + } + } + + if(dirEntryIndex == -1){ + return 0; + } + + lfnEntries = (fat_lfn_entry_t**)kmalloc(sizeof(fat_lfn_entry_t*) * lfnCount); + + for(unsigned i = 0; i < lfnCount; i++){ + fat_lfn_entry_t* lfnEntry = (fat_lfn_entry_t*)(&dirEntries[dirEntryIndex - i - 1]); + + lfnEntries[i] = lfnEntry; + } + + if(lfnCount){ + GetLongFilename(dirent->name, lfnEntries, lfnCount); + } else { + strncpy(dirent->name, (char*)dirEntry->filename, 8); + while(strchr(dirent->name, ' ')) *strchr(dirent->name, ' ') = 0; // Remove Spaces + if(strchr((char*)dirEntry->ext, ' ') != (char*)dirEntry->ext){ + strncpy(dirent->name + strlen(dirent->name), ".", 1); + strncpy(dirent->name + strlen(dirent->name), (char*)dirEntry->ext, 3); + } + } + + if(dirEntry->attributes & FAT_ATTR_DIRECTORY) dirent->flags = DT_DIR; + else dirent->flags = DT_REG; + + return 1; + } + + FsNode* Fat32Volume::FindDir(Fat32Node* node, char* name){ + unsigned lfnCount = 0; + + uint32_t cluster = node->inode; + int clusterCount = 0; + + fat_entry_t* dirEntries = (fat_entry_t*)ReadClusterChain(cluster, &clusterCount); + + List foundEntries; + List foundEntriesLfnCount; + + fat_lfn_entry_t** lfnEntries; + Fat32Node* _node = nullptr; + + for(unsigned i = 0; i < static_cast(clusterCount) * clusterSizeBytes; i++){ + if(dirEntries[i].filename[0] == 0) return nullptr; // No Directory Entry at index + else if (dirEntries[i].filename[0] == 0xE5) { + lfnCount = 0; + continue; // Unused Entry + } + else if (dirEntries[i].attributes == 0x0F) lfnCount++; // Long File Name Entry + else if (dirEntries[i].attributes & 0x08 /*Volume ID*/){ + lfnCount = 0; + continue; + } else { + char* _name = (char*)kmalloc(128); + if(lfnCount){ + lfnEntries = (fat_lfn_entry_t**)kmalloc(sizeof(fat_lfn_entry_t*) * lfnCount); + + for(unsigned k = 0; k < lfnCount; k++){ + fat_lfn_entry_t* lfnEntry = (fat_lfn_entry_t*)(&dirEntries[i - k - 1]); + + lfnEntries[k] = lfnEntry; + } + + GetLongFilename(_name, lfnEntries, lfnCount); + + kfree(lfnEntries); + } else { + strncpy(_name, (char*)dirEntries[i].filename, 8); + while(strchr(_name, ' ')) *strchr(_name, ' ') = 0; // Remove Spaces + if(strchr((char*)dirEntries[i].ext, ' ') != (char*)dirEntries[i].ext){ + strncpy(_name + strlen(_name), ".", 1); + strncpy(_name + strlen(_name), (char*)dirEntries[i].ext, 3); + } + } + + if(strcmp(_name, name) == 0){ + uint64_t clusterNum = (((uint32_t)dirEntries[i].highClusterNum) << 16) | dirEntries[i].lowClusterNum; + if(clusterNum == bootRecord->ebr.rootClusterNum || clusterNum == 0) + return mountPoint; // Root Directory + _node = new Fat32Node(); + _node->size = dirEntries[i].fileSize; + _node->inode = clusterNum; + if(dirEntries[i].attributes & FAT_ATTR_DIRECTORY) _node->flags = FS_NODE_DIRECTORY; + else _node->flags = FS_NODE_FILE; + break; + } + lfnCount = 0; + } + } + + if(_node){ + _node->vol = this; + } + + return _node; + } + + ssize_t Fat32Node::Read(size_t offset, size_t size, uint8_t *buffer){ + return vol->Read(this, offset, size, buffer); + } + + ssize_t Fat32Node::Write(size_t offset, size_t size, uint8_t *buffer){ + return vol->Write(this, offset, size, buffer); + } + + /*fs_fd_t* Fat32Node::Open(uint32_t flags){ + vol->Open(this, flags); + } + + void Fat32Node::Close(){ + vol->Close(this); + }*/ + + int Fat32Node::ReadDir(DirectoryEntry* dirent, uint32_t index){ + return vol->ReadDir(this, dirent, index); + } + + FsNode* Fat32Node::FindDir(char* name){ + return vol->FindDir(this, name); + } } \ No newline at end of file diff --git a/Kernel/src/fs/filesystem.cpp b/Kernel/src/fs/filesystem.cpp index 40060bd1..cbddb6f5 100755 --- a/Kernel/src/fs/filesystem.cpp +++ b/Kernel/src/fs/filesystem.cpp @@ -1,574 +1,574 @@ -#include - -#include -#include -#include - -namespace fs{ - volume_id_t nextVID = 1; // Next volume ID - - class Root : public FsNode { - public: - Root() { - inode = 0; - flags = FS_NODE_DIRECTORY; - } - - int ReadDir(DirectoryEntry*, uint32_t); - FsNode* FindDir(char* name); - }; - - Root root; - DirectoryEntry rootDirent = DirectoryEntry(&root, ""); - - List* volumes; - - DirectoryEntry* devices[64]; - uint32_t deviceCount = 0; - - void Initialize(){ - volumes = new List(); - } - - volume_id_t GetVolumeID(){ - return nextVID++; - } - - void RegisterVolume(FsVolume* vol){ - vol->mountPoint->parent = &root; - vol->volumeID = GetVolumeID(); - volumes->add_back(vol); - } - - FsNode* GetRoot(){ - return &root; - } - - FsNode* FollowLink(FsNode* link, FsNode* workingDir){ - assert(link); - - char buffer[PATH_MAX + 1]; - - auto bytesRead = link->ReadLink(buffer, PATH_MAX); - if(bytesRead < 0){ - Log::Warning("FollowLink: Readlink error %d", -bytesRead); - return nullptr; - } - buffer[bytesRead] = 0; // Null terminate - - FsNode* node = ResolvePath(buffer, workingDir, false); - - if(!node){ - Log::Warning("FollowLink: Failed to resolve symlink %s!", buffer); - } - return node; - } - - FsNode* ResolvePath(const char* path, const char* workingDir, bool followSymlinks){ - assert(path); - - char* tempPath; - if(workingDir && path[0] != '/'){ // If the path starts with '/' then treat as an absolute path - tempPath = (char*)kmalloc(strlen(path) + strlen(workingDir) + 2); - strcpy(tempPath, workingDir); - strcpy(tempPath + strlen(tempPath), "/"); - strcpy(tempPath + strlen(tempPath), path); - } else { - tempPath = (char*)kmalloc(strlen(path) + 1); - strcpy(tempPath, path); - } - - FsNode* root = fs::GetRoot(); - FsNode* currentNode = root; - - char* file = strtok(tempPath,"/"); - - while(file != NULL){ // Iterate through the directories to find the file - FsNode* node = fs::FindDir(currentNode,file); - if(!node) { - Log::Warning("%s not found!", file); - kfree(tempPath); - return nullptr; - } - - size_t amountOfSymlinks = 0; - while(((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks - if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ - Log::Warning("ResolvePath: Reached maximum number of symlinks"); - return nullptr; - } - - node = FollowLink(node, currentNode); - - if(!node){ - Log::Warning("ResolvePath: Unresolved symlink!"); - kfree(tempPath); - return node; - } - } - - if((node->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ - currentNode = node; - file = strtok(NULL, "/"); - continue; - } - - if((file = strtok(NULL, "/"))){ - Log::Warning("%s is not a directory!", file); - kfree(tempPath); - return nullptr; - } - - amountOfSymlinks = 0; - while(followSymlinks && ((currentNode->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks - if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ - Log::Warning("ResolvePath: Reached maximum number of symlinks"); - return nullptr; - } - - currentNode = FollowLink(node, currentNode); - - if(!node){ - Log::Warning("ResolvePath: Unresolved symlink!"); - kfree(tempPath); - return node; - } - } - - currentNode = node; - break; - } - kfree(tempPath); - return currentNode; - } - - FsNode* ResolvePath(const char* path, FsNode* workingDir, bool followSymlinks){ - FsNode* root = fs::GetRoot(); - FsNode* currentNode = root; - - char* tempPath = (char*)kmalloc(strlen(path) + 1); - strcpy(tempPath, path); - - if(workingDir && path[0] != '/'){ - currentNode = workingDir; - } - - char* file = strtok(tempPath,"/"); - - while(file != NULL){ // Iterate through the directories to find the file - FsNode* node = fs::FindDir(currentNode,file); - if(!node) { - Log::Warning("%s not found!", path); - return nullptr; - } - - size_t amountOfSymlinks = 0; - while(followSymlinks && ((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks - if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ - Log::Warning("ResolvePath: Reached maximum number of symlinks"); - return nullptr; - } - - node = FollowLink(node, currentNode); - - if(!node){ - Log::Warning("ResolvePath: Unresolved symlink!"); - kfree(tempPath); - return node; - } - } - - if((node->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ - currentNode = node; - file = strtok(NULL, "/"); - continue; - } - - if((file = strtok(NULL, "/"))){ - Log::Warning("%s is not a directory!", file); - return nullptr; - } - - amountOfSymlinks = 0; - while(followSymlinks && ((currentNode->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks - if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ - Log::Warning("ResolvePath: Reached maximum number of symlinks"); - return nullptr; - } - - currentNode = FollowLink(node, currentNode); - - if(!node){ - Log::Warning("ResolvePath: Unresolved symlink!"); - kfree(tempPath); - return currentNode; - } - } - currentNode = node; - break; - } - - kfree(tempPath); - return currentNode; - } - - FsNode* ResolveParent(const char* path, const char* workingDir){ - char* pathCopy = (char*)kmalloc(strlen(path) + 1); - strcpy(pathCopy, path); - - if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash - pathCopy[strlen(pathCopy) - 1] = 0; - } - - char* dirPath = strrchr(pathCopy, '/'); - - FsNode* parentDirectory = nullptr; - - if(dirPath == nullptr){ - parentDirectory = fs::ResolvePath(workingDir); - } else { - *(dirPath - 1) = 0; // Cut off the directory name from the path copy - parentDirectory = fs::ResolvePath(pathCopy, workingDir); - } - - kfree(pathCopy); - return parentDirectory; - } - - FsNode* ResolveParent(const char* path, FsNode* workingDir){ - char* pathCopy = (char*)kmalloc(strlen(path) + 1); - strcpy(pathCopy, path); - - if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash - pathCopy[strlen(pathCopy) - 1] = 0; - } - - char* dirPath = strrchr(pathCopy, '/'); - - FsNode* parentDirectory = nullptr; - - if(dirPath == nullptr){ - parentDirectory = workingDir; - } else { - *(dirPath - 1) = 0; // Cut off the directory name from the path copy - parentDirectory = fs::ResolvePath(pathCopy, workingDir); - } - - kfree(pathCopy); - return parentDirectory; - } - - char* CanonicalizePath(const char* path, char* workingDir){ - char* tempPath; - if(workingDir && path[0] != '/'){ - tempPath = (char*)kmalloc(strlen(path) + strlen(workingDir) + 2); - strcpy(tempPath, workingDir); - strcpy(tempPath + strlen(tempPath), "/"); - strcpy(tempPath + strlen(tempPath), path); - } else { - tempPath = (char*)kmalloc(strlen(path) + 1); - strcpy(tempPath, path); - } - - char* file = strtok(tempPath,"/"); - List* tokens = new List(); - - while(file != NULL){ - tokens->add_back(file); - file = strtok(NULL, "/"); - } - - int newLength = 2; // Separator and null terminator - newLength += strlen(path) + strlen(workingDir); - for(unsigned i = 0; i < tokens->get_length(); i++){ - if(strlen(tokens->get_at(i)) == 0){ - tokens->remove_at(i--); - continue; - } else if(strcmp(tokens->get_at(i), ".") == 0){ - tokens->remove_at(i--); - continue; - } else if(strcmp(tokens->get_at(i), "..") == 0){ - if(i){ - tokens->remove_at(i); - tokens->remove_at(i - 1); - i -= 2; - } else tokens->remove_at(i); - continue; - } - - newLength += strlen(tokens->get_at(i)) + 1; // Name and separator - } - - char* outPath = (char*)kmalloc(newLength); - outPath[0] = 0; - - if(!tokens->get_length()) strcpy(outPath + strlen(outPath), "/"); - else for(unsigned i = 0; i < tokens->get_length(); i++){ - strcpy(outPath + strlen(outPath), "/"); - strcpy(outPath + strlen(outPath), tokens->get_at(i)); - } - - kfree(tempPath); - delete tokens; - - return outPath; - } - - char* BaseName(const char* path){ - char* pathCopy = (char*)kmalloc(strlen(path) + 1); - strcpy(pathCopy, path); - - if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash - pathCopy[strlen(pathCopy) - 1] = 0; - } - - char* basename = nullptr; - char* temp; - if((temp = strrchr(pathCopy, '/'))){ - basename = (char*)kmalloc(strlen(temp) + 1); - strcpy(basename, temp); - - kfree(pathCopy); - } else { - basename = pathCopy; - } - - return basename; - } - - int Root::ReadDir(DirectoryEntry* dirent, uint32_t index){ - if (index < fs::volumes->get_length()){ - *dirent = (volumes->get_at(index)->mountPointDirent); - return 1; - } else return 0; - } - - FsNode* Root::FindDir(char* name){ - if(strcmp(name, ".") == 0) return this; - if(strcmp(name, "..") == 0) return this; - - for(unsigned i = 0; i < fs::volumes->get_length(); i++){ - if(strcmp(fs::volumes->get_at(i)->mountPointDirent.name,name) == 0) return (fs::volumes->get_at(i)->mountPointDirent.node); - } - - return NULL; - } - - ssize_t Read(FsNode* node, size_t offset, size_t size, uint8_t *buffer){ - assert(node); - - return node->Read(offset,size,buffer); - } - - ssize_t Write(FsNode* node, size_t offset, size_t size, uint8_t *buffer){ - assert(node); - - return node->Write(offset,size,buffer); - } - - fs_fd_t* Open(FsNode* node, uint32_t flags){ - /*if((node->flags & S_IFMT) == S_IFLNK){ - char pathBuffer[PATH_MAX]; - - ssize_t bytesRead = node->ReadLink(pathBuffer, PATH_MAX); - if(bytesRead < 0){ - Log::Warning("fs::Open: Readlink error"); - return nullptr; - } - pathBuffer[bytesRead] = 0; // Null terminate - - FsNode* link = fs::ResolvePath(pathBuffer); - if(!link){ - Log::Warning("fs::Open: Invalid symbolic link"); - } - return link->Open(flags); - }*/ - - return node->Open(flags); - } - - int Link(FsNode* dir, FsNode* link, DirectoryEntry* ent){ - assert(dir); - assert(link); - - return dir->Link(link, ent); - } - - int Unlink(FsNode* dir, DirectoryEntry* ent, bool unlinkDirectories){ - assert(dir); - assert(ent); - - return dir->Unlink(ent, unlinkDirectories); - } - - void Close(FsNode* node){ - return node->Close(); - } - - void Close(fs_fd_t* fd){ - if(!fd) return; - - fd->node->Close(); - fd->node = nullptr; - - kfree(fd); - } - - int ReadDir(FsNode* node, DirectoryEntry* dirent, uint32_t index){ - assert(node); - - //if((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK) return ReadDir(node->link, dirent, index); - - return node->ReadDir(dirent, index); - } - - FsNode* FindDir(FsNode* node, char* name){ - assert(node); - - //if((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK) return FindDir(node->link, name); - - return node->FindDir(name); - } - - ssize_t Read(fs_fd_t* handle, size_t size, uint8_t *buffer){ - if(handle->node){ - ssize_t ret = Read(handle->node,handle->pos,size,buffer); - - if(ret >= 0){ - handle->pos += ret; - } - - return ret; - } - else return 0; - } - - ssize_t Write(fs_fd_t* handle, size_t size, uint8_t *buffer){ - if(handle->node){ - off_t ret = Write(handle->node,handle->pos,size,buffer); - - if(ret >= 0){ - handle->pos += ret; - } - - return ret; - } else return -1; - } - - int ReadDir(fs_fd_t* handle, DirectoryEntry* dirent, uint32_t index){ - if(handle->node) - return ReadDir(handle->node, dirent, index); - else return 0; - } - - FsNode* FindDir(fs_fd_t* handle, char* name){ - if(handle->node) - return FindDir(handle->node,name); - else return 0; - } - - int Ioctl(fs_fd_t* handle, uint64_t cmd, uint64_t arg){ - if(handle->node) return handle->node->Ioctl(cmd, arg); - else return -1; - } - - int Rename(FsNode* olddir, char* oldpath, FsNode* newdir, char* newpath){ - assert(olddir && newdir); - - if((olddir->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ - return -ENOTDIR; - } - - if((newdir->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ - return -ENOTDIR; - } - - FsNode* oldnode = ResolvePath(oldpath, olddir); - - if(!oldnode){ - return -ENOENT; - } - - if((oldnode->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ - Log::Warning("Filesystem: Rename: We do not support using rename on directories yet!"); - return -ENOSYS; - } - - FsNode* newpathParent = ResolveParent(newpath, newdir); - - if(!newpathParent){ - return -ENOENT; - } else if((newpathParent->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ - return -ENOTDIR; // Parent of newpath is not a directory - } - - FsNode* newnode = ResolvePath(newpath, newdir); - - if(newnode){ - if((newnode->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ - return -EISDIR; // If it exists newpath must not be a directory - } - } - - DirectoryEntry oldpathDirent; - strncpy(oldpathDirent.name, fs::BaseName(oldpath), NAME_MAX); - - DirectoryEntry newpathDirent; - strncpy(newpathDirent.name, fs::BaseName(newpath), NAME_MAX); - - if((oldnode->flags & FS_NODE_TYPE) != FS_NODE_SYMLINK && oldnode->volumeID == newpathParent->volumeID){ // Easy shit we can just link and unlink - FsNode* oldpathParent = fs::ResolveParent(oldpath, olddir); - assert(oldpathParent); // If this is null something went horribly wrong - - if(newnode){ - if(auto e = newpathParent->Unlink(&newpathDirent)){ - return e; // Unlink error - } - } - - if(auto e = newpathParent->Link(oldnode, &newpathDirent)){ - return e; // Link error - } - - if(auto e = oldpathParent->Unlink(&oldpathDirent)){ - return e; // Unlink error - } - } else if((oldnode->flags & FS_NODE_TYPE) != FS_NODE_SYMLINK) { // Aight we have to copy it - FsNode* oldpathParent = fs::ResolveParent(oldpath, olddir); - assert(oldpathParent); // If this is null something went horribly wrong - - if(auto e = newpathParent->Create(&newpathDirent, 0)){ - return e; // Create error - } - - newnode = ResolvePath(newpath, newdir); - if(!newnode){ - Log::Warning("Filesystem: Rename: newpath was created with no error returned however it was unable to be found."); - return -ENOENT; - } - - uint8_t* buffer = (uint8_t*)kmalloc(oldnode->size); - - ssize_t rret = oldnode->Read(0, oldnode->size, buffer); - if(rret < 0){ - Log::Warning("Filesystem: Rename: Error reading oldpath"); - return rret; - } - - ssize_t wret = oldnode->Write(0, rret, buffer); - if(wret < 0){ - Log::Warning("Filesystem: Rename: Error reading oldpath"); - return wret; - } - - if(auto e = oldpathParent->Unlink(&oldpathDirent)){ - return e; // Unlink error - } - } else { - Log::Warning("Filesystem: Rename: We do not support using rename on symlinks yet!"); // TODO: Rename the symlink - return -ENOSYS; - } - - return 0; - } +#include + +#include +#include +#include + +namespace fs{ + volume_id_t nextVID = 1; // Next volume ID + + class Root : public FsNode { + public: + Root() { + inode = 0; + flags = FS_NODE_DIRECTORY; + } + + int ReadDir(DirectoryEntry*, uint32_t); + FsNode* FindDir(char* name); + }; + + Root root; + DirectoryEntry rootDirent = DirectoryEntry(&root, ""); + + List* volumes; + + DirectoryEntry* devices[64]; + uint32_t deviceCount = 0; + + void Initialize(){ + volumes = new List(); + } + + volume_id_t GetVolumeID(){ + return nextVID++; + } + + void RegisterVolume(FsVolume* vol){ + vol->mountPoint->parent = &root; + vol->volumeID = GetVolumeID(); + volumes->add_back(vol); + } + + FsNode* GetRoot(){ + return &root; + } + + FsNode* FollowLink(FsNode* link, FsNode* workingDir){ + assert(link); + + char buffer[PATH_MAX + 1]; + + auto bytesRead = link->ReadLink(buffer, PATH_MAX); + if(bytesRead < 0){ + Log::Warning("FollowLink: Readlink error %d", -bytesRead); + return nullptr; + } + buffer[bytesRead] = 0; // Null terminate + + FsNode* node = ResolvePath(buffer, workingDir, false); + + if(!node){ + Log::Warning("FollowLink: Failed to resolve symlink %s!", buffer); + } + return node; + } + + FsNode* ResolvePath(const char* path, const char* workingDir, bool followSymlinks){ + assert(path); + + char* tempPath; + if(workingDir && path[0] != '/'){ // If the path starts with '/' then treat as an absolute path + tempPath = (char*)kmalloc(strlen(path) + strlen(workingDir) + 2); + strcpy(tempPath, workingDir); + strcpy(tempPath + strlen(tempPath), "/"); + strcpy(tempPath + strlen(tempPath), path); + } else { + tempPath = (char*)kmalloc(strlen(path) + 1); + strcpy(tempPath, path); + } + + FsNode* root = fs::GetRoot(); + FsNode* currentNode = root; + + char* file = strtok(tempPath,"/"); + + while(file != NULL){ // Iterate through the directories to find the file + FsNode* node = fs::FindDir(currentNode,file); + if(!node) { + Log::Warning("%s not found!", file); + kfree(tempPath); + return nullptr; + } + + size_t amountOfSymlinks = 0; + while(((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks + if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ + Log::Warning("ResolvePath: Reached maximum number of symlinks"); + return nullptr; + } + + node = FollowLink(node, currentNode); + + if(!node){ + Log::Warning("ResolvePath: Unresolved symlink!"); + kfree(tempPath); + return node; + } + } + + if((node->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ + currentNode = node; + file = strtok(NULL, "/"); + continue; + } + + if((file = strtok(NULL, "/"))){ + Log::Warning("%s is not a directory!", file); + kfree(tempPath); + return nullptr; + } + + amountOfSymlinks = 0; + while(followSymlinks && ((currentNode->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks + if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ + Log::Warning("ResolvePath: Reached maximum number of symlinks"); + return nullptr; + } + + currentNode = FollowLink(node, currentNode); + + if(!node){ + Log::Warning("ResolvePath: Unresolved symlink!"); + kfree(tempPath); + return node; + } + } + + currentNode = node; + break; + } + kfree(tempPath); + return currentNode; + } + + FsNode* ResolvePath(const char* path, FsNode* workingDir, bool followSymlinks){ + FsNode* root = fs::GetRoot(); + FsNode* currentNode = root; + + char* tempPath = (char*)kmalloc(strlen(path) + 1); + strcpy(tempPath, path); + + if(workingDir && path[0] != '/'){ + currentNode = workingDir; + } + + char* file = strtok(tempPath,"/"); + + while(file != NULL){ // Iterate through the directories to find the file + FsNode* node = fs::FindDir(currentNode,file); + if(!node) { + Log::Warning("%s not found!", path); + return nullptr; + } + + size_t amountOfSymlinks = 0; + while(followSymlinks && ((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks + if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ + Log::Warning("ResolvePath: Reached maximum number of symlinks"); + return nullptr; + } + + node = FollowLink(node, currentNode); + + if(!node){ + Log::Warning("ResolvePath: Unresolved symlink!"); + kfree(tempPath); + return node; + } + } + + if((node->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ + currentNode = node; + file = strtok(NULL, "/"); + continue; + } + + if((file = strtok(NULL, "/"))){ + Log::Warning("%s is not a directory!", file); + return nullptr; + } + + amountOfSymlinks = 0; + while(followSymlinks && ((currentNode->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK)){ // Check for symlinks + if(amountOfSymlinks++ > MAXIMUM_SYMLINK_AMOUNT){ + Log::Warning("ResolvePath: Reached maximum number of symlinks"); + return nullptr; + } + + currentNode = FollowLink(node, currentNode); + + if(!node){ + Log::Warning("ResolvePath: Unresolved symlink!"); + kfree(tempPath); + return currentNode; + } + } + currentNode = node; + break; + } + + kfree(tempPath); + return currentNode; + } + + FsNode* ResolveParent(const char* path, const char* workingDir){ + char* pathCopy = (char*)kmalloc(strlen(path) + 1); + strcpy(pathCopy, path); + + if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash + pathCopy[strlen(pathCopy) - 1] = 0; + } + + char* dirPath = strrchr(pathCopy, '/'); + + FsNode* parentDirectory = nullptr; + + if(dirPath == nullptr){ + parentDirectory = fs::ResolvePath(workingDir); + } else { + *(dirPath - 1) = 0; // Cut off the directory name from the path copy + parentDirectory = fs::ResolvePath(pathCopy, workingDir); + } + + kfree(pathCopy); + return parentDirectory; + } + + FsNode* ResolveParent(const char* path, FsNode* workingDir){ + char* pathCopy = (char*)kmalloc(strlen(path) + 1); + strcpy(pathCopy, path); + + if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash + pathCopy[strlen(pathCopy) - 1] = 0; + } + + char* dirPath = strrchr(pathCopy, '/'); + + FsNode* parentDirectory = nullptr; + + if(dirPath == nullptr){ + parentDirectory = workingDir; + } else { + *(dirPath - 1) = 0; // Cut off the directory name from the path copy + parentDirectory = fs::ResolvePath(pathCopy, workingDir); + } + + kfree(pathCopy); + return parentDirectory; + } + + char* CanonicalizePath(const char* path, char* workingDir){ + char* tempPath; + if(workingDir && path[0] != '/'){ + tempPath = (char*)kmalloc(strlen(path) + strlen(workingDir) + 2); + strcpy(tempPath, workingDir); + strcpy(tempPath + strlen(tempPath), "/"); + strcpy(tempPath + strlen(tempPath), path); + } else { + tempPath = (char*)kmalloc(strlen(path) + 1); + strcpy(tempPath, path); + } + + char* file = strtok(tempPath,"/"); + List* tokens = new List(); + + while(file != NULL){ + tokens->add_back(file); + file = strtok(NULL, "/"); + } + + int newLength = 2; // Separator and null terminator + newLength += strlen(path) + strlen(workingDir); + for(unsigned i = 0; i < tokens->get_length(); i++){ + if(strlen(tokens->get_at(i)) == 0){ + tokens->remove_at(i--); + continue; + } else if(strcmp(tokens->get_at(i), ".") == 0){ + tokens->remove_at(i--); + continue; + } else if(strcmp(tokens->get_at(i), "..") == 0){ + if(i){ + tokens->remove_at(i); + tokens->remove_at(i - 1); + i -= 2; + } else tokens->remove_at(i); + continue; + } + + newLength += strlen(tokens->get_at(i)) + 1; // Name and separator + } + + char* outPath = (char*)kmalloc(newLength); + outPath[0] = 0; + + if(!tokens->get_length()) strcpy(outPath + strlen(outPath), "/"); + else for(unsigned i = 0; i < tokens->get_length(); i++){ + strcpy(outPath + strlen(outPath), "/"); + strcpy(outPath + strlen(outPath), tokens->get_at(i)); + } + + kfree(tempPath); + delete tokens; + + return outPath; + } + + char* BaseName(const char* path){ + char* pathCopy = (char*)kmalloc(strlen(path) + 1); + strcpy(pathCopy, path); + + if(pathCopy[strlen(pathCopy) - 1] == '/'){ // Remove trailing slash + pathCopy[strlen(pathCopy) - 1] = 0; + } + + char* basename = nullptr; + char* temp; + if((temp = strrchr(pathCopy, '/'))){ + basename = (char*)kmalloc(strlen(temp) + 1); + strcpy(basename, temp); + + kfree(pathCopy); + } else { + basename = pathCopy; + } + + return basename; + } + + int Root::ReadDir(DirectoryEntry* dirent, uint32_t index){ + if (index < fs::volumes->get_length()){ + *dirent = (volumes->get_at(index)->mountPointDirent); + return 1; + } else return 0; + } + + FsNode* Root::FindDir(char* name){ + if(strcmp(name, ".") == 0) return this; + if(strcmp(name, "..") == 0) return this; + + for(unsigned i = 0; i < fs::volumes->get_length(); i++){ + if(strcmp(fs::volumes->get_at(i)->mountPointDirent.name,name) == 0) return (fs::volumes->get_at(i)->mountPointDirent.node); + } + + return NULL; + } + + ssize_t Read(FsNode* node, size_t offset, size_t size, uint8_t *buffer){ + assert(node); + + return node->Read(offset,size,buffer); + } + + ssize_t Write(FsNode* node, size_t offset, size_t size, uint8_t *buffer){ + assert(node); + + return node->Write(offset,size,buffer); + } + + fs_fd_t* Open(FsNode* node, uint32_t flags){ + /*if((node->flags & S_IFMT) == S_IFLNK){ + char pathBuffer[PATH_MAX]; + + ssize_t bytesRead = node->ReadLink(pathBuffer, PATH_MAX); + if(bytesRead < 0){ + Log::Warning("fs::Open: Readlink error"); + return nullptr; + } + pathBuffer[bytesRead] = 0; // Null terminate + + FsNode* link = fs::ResolvePath(pathBuffer); + if(!link){ + Log::Warning("fs::Open: Invalid symbolic link"); + } + return link->Open(flags); + }*/ + + return node->Open(flags); + } + + int Link(FsNode* dir, FsNode* link, DirectoryEntry* ent){ + assert(dir); + assert(link); + + return dir->Link(link, ent); + } + + int Unlink(FsNode* dir, DirectoryEntry* ent, bool unlinkDirectories){ + assert(dir); + assert(ent); + + return dir->Unlink(ent, unlinkDirectories); + } + + void Close(FsNode* node){ + return node->Close(); + } + + void Close(fs_fd_t* fd){ + if(!fd) return; + + fd->node->Close(); + fd->node = nullptr; + + kfree(fd); + } + + int ReadDir(FsNode* node, DirectoryEntry* dirent, uint32_t index){ + assert(node); + + //if((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK) return ReadDir(node->link, dirent, index); + + return node->ReadDir(dirent, index); + } + + FsNode* FindDir(FsNode* node, char* name){ + assert(node); + + //if((node->flags & FS_NODE_TYPE) == FS_NODE_SYMLINK) return FindDir(node->link, name); + + return node->FindDir(name); + } + + ssize_t Read(fs_fd_t* handle, size_t size, uint8_t *buffer){ + if(handle->node){ + ssize_t ret = Read(handle->node,handle->pos,size,buffer); + + if(ret >= 0){ + handle->pos += ret; + } + + return ret; + } + else return 0; + } + + ssize_t Write(fs_fd_t* handle, size_t size, uint8_t *buffer){ + if(handle->node){ + off_t ret = Write(handle->node,handle->pos,size,buffer); + + if(ret >= 0){ + handle->pos += ret; + } + + return ret; + } else return -1; + } + + int ReadDir(fs_fd_t* handle, DirectoryEntry* dirent, uint32_t index){ + if(handle->node) + return ReadDir(handle->node, dirent, index); + else return 0; + } + + FsNode* FindDir(fs_fd_t* handle, char* name){ + if(handle->node) + return FindDir(handle->node,name); + else return 0; + } + + int Ioctl(fs_fd_t* handle, uint64_t cmd, uint64_t arg){ + if(handle->node) return handle->node->Ioctl(cmd, arg); + else return -1; + } + + int Rename(FsNode* olddir, char* oldpath, FsNode* newdir, char* newpath){ + assert(olddir && newdir); + + if((olddir->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ + return -ENOTDIR; + } + + if((newdir->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ + return -ENOTDIR; + } + + FsNode* oldnode = ResolvePath(oldpath, olddir); + + if(!oldnode){ + return -ENOENT; + } + + if((oldnode->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ + Log::Warning("Filesystem: Rename: We do not support using rename on directories yet!"); + return -ENOSYS; + } + + FsNode* newpathParent = ResolveParent(newpath, newdir); + + if(!newpathParent){ + return -ENOENT; + } else if((newpathParent->flags & FS_NODE_TYPE) != FS_NODE_DIRECTORY){ + return -ENOTDIR; // Parent of newpath is not a directory + } + + FsNode* newnode = ResolvePath(newpath, newdir); + + if(newnode){ + if((newnode->flags & FS_NODE_TYPE) == FS_NODE_DIRECTORY){ + return -EISDIR; // If it exists newpath must not be a directory + } + } + + DirectoryEntry oldpathDirent; + strncpy(oldpathDirent.name, fs::BaseName(oldpath), NAME_MAX); + + DirectoryEntry newpathDirent; + strncpy(newpathDirent.name, fs::BaseName(newpath), NAME_MAX); + + if((oldnode->flags & FS_NODE_TYPE) != FS_NODE_SYMLINK && oldnode->volumeID == newpathParent->volumeID){ // Easy shit we can just link and unlink + FsNode* oldpathParent = fs::ResolveParent(oldpath, olddir); + assert(oldpathParent); // If this is null something went horribly wrong + + if(newnode){ + if(auto e = newpathParent->Unlink(&newpathDirent)){ + return e; // Unlink error + } + } + + if(auto e = newpathParent->Link(oldnode, &newpathDirent)){ + return e; // Link error + } + + if(auto e = oldpathParent->Unlink(&oldpathDirent)){ + return e; // Unlink error + } + } else if((oldnode->flags & FS_NODE_TYPE) != FS_NODE_SYMLINK) { // Aight we have to copy it + FsNode* oldpathParent = fs::ResolveParent(oldpath, olddir); + assert(oldpathParent); // If this is null something went horribly wrong + + if(auto e = newpathParent->Create(&newpathDirent, 0)){ + return e; // Create error + } + + newnode = ResolvePath(newpath, newdir); + if(!newnode){ + Log::Warning("Filesystem: Rename: newpath was created with no error returned however it was unable to be found."); + return -ENOENT; + } + + uint8_t* buffer = (uint8_t*)kmalloc(oldnode->size); + + ssize_t rret = oldnode->Read(0, oldnode->size, buffer); + if(rret < 0){ + Log::Warning("Filesystem: Rename: Error reading oldpath"); + return rret; + } + + ssize_t wret = oldnode->Write(0, rret, buffer); + if(wret < 0){ + Log::Warning("Filesystem: Rename: Error reading oldpath"); + return wret; + } + + if(auto e = oldpathParent->Unlink(&oldpathDirent)){ + return e; // Unlink error + } + } else { + Log::Warning("Filesystem: Rename: We do not support using rename on symlinks yet!"); // TODO: Rename the symlink + return -ENOSYS; + } + + return 0; + } } \ No newline at end of file diff --git a/Kernel/src/fs/initrd.cpp b/Kernel/src/fs/initrd.cpp index 0f62be18..bf804193 100755 --- a/Kernel/src/fs/initrd.cpp +++ b/Kernel/src/fs/initrd.cpp @@ -1,205 +1,205 @@ -/* - * - * Old Initrd Format, no longer used - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace Initrd{ - int ReadDir(fs_node_t* node, fs_dirent_t* dirent, uint32_t index); - fs_node_t* FindDir(fs_node_t* node, char* name); - - size_t Read(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); - size_t ReadNull(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); - - void Open(fs_node_t* node, uint32_t flags); - void Close(fs_node_t* node); - - size_t Write(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); - - lemoninitfs_header_t initrdHeader; - lemoninitfs_node_t* nodes; - fs_node_t* fsNodes; - - //fs_dirent_t dirent; - - void* initrd_address; - - InitrdVolume* vol; - - void Initialize(uintptr_t address, uint32_t size) { - #ifdef Lemon32 - void* virtual_address = (void*)Memory::KernelAllocateVirtualPages(size / PAGE_SIZE + 1); - Memory::MapVirtualPages(address, (uint32_t)virtual_address, size / PAGE_SIZE + 1); - initrd_address = virtual_address; - #endif - #ifdef Lemon64 - initrd_address = (void*)address; - #endif - Log::Info("Initrd address: "); - Log::Info(address); - Log::Info("Size:"); - Log::Info(size, false); - Log::Info("File Count:"); - Log::Info(*((uint32_t*)initrd_address), false); - Log::Write("files\r\n"); - initrdHeader = *(lemoninitfs_header_t*)initrd_address; - nodes = (lemoninitfs_node_t*)(initrd_address + sizeof(lemoninitfs_header_t)); - fsNodes = (fs_node_t*)kmalloc(sizeof(fs_node_t)*initrdHeader.fileCount); - - for(int i = 0; i < initrdHeader.fileCount; i++){ - fs_node_t* node = &(fsNodes[i]); - strcpy(node->name,nodes[i].filename); - node->inode = i; - node->flags = FS_NODE_FILE; - node->read = Initrd::Read; - node->write = Initrd::Write; - node->open = Initrd::Open; - node->close = Initrd::Close; - node->size = nodes[i].size; - } - - vol = new InitrdVolume(); - - fs::volumes->add_back(vol); - - InitrdVolume* vol2 = new InitrdVolume(); // Very Cheap Workaround - strcpy(vol2->mountPoint.name, "lib"); - strcpy(vol2->mountPointDirent.name, "lib"); - - fs::volumes->add_back(vol2); - } - - size_t Read(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer){ - lemoninitfs_node_t inode = nodes[node->inode]; - - if(offset > inode.size) return 0; - else if(offset + size > inode.size || size > inode.size) size = inode.size - offset; - - if(!size) return 0; - - memcpy(buffer, (void*)((uintptr_t)inode.offset + (uintptr_t)initrd_address + offset), size); - return size; - } - - size_t Write(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer){ - return 0; // It's a ramdisk. - } - - void Open(fs_node_t* node, uint32_t flags){ - - } - - void Close(fs_node_t* node){ - - } - - int ReadDir(fs_node_t* node, fs_dirent_t* dirent, uint32_t index){ - if(index >= initrdHeader.fileCount + 2) return -1; - - if(index == 0) { - memset(dirent->name,0,128); // Zero the string - strcpy(dirent->name,"."); - dirent->inode = 0; - dirent->type = FS_NODE_DIRECTORY; - return 0; - } else if (index == 1){ - memset(dirent->name,0,128); // Zero the string - strcpy(dirent->name,".."); - dirent->inode = 2; - dirent->type = FS_NODE_DIRECTORY; - return 0; - } - memset(dirent->name,0,128); // Zero the string - strcpy(dirent->name,nodes[index - 2].filename); - dirent->inode = index - 3; - dirent->type = 0; - - return 0; - } - - fs_node_t* FindDir(fs_node_t* node, char* name) { - for(int i = 0; i < initrdHeader.fileCount;i++){ - if(strcmp(fsNodes[i].name,name) == 0) return &(fsNodes[i]); - } - - if(strcmp(".", name) == 0) return node; - if(strcmp("..", name) == 0) return fs::GetRoot(); - - return NULL; - } - - - lemoninitfs_node_t* List() { - return nodes; - } - - lemoninitfs_header_t* GetHeader() { - return &initrdHeader; - } - - void* Read(int node) { - return (void*)(nodes[node].offset+(uintptr_t)initrd_address); - } - - uint8_t* Read(lemoninitfs_node_t node, uint8_t* buffer) { - memcpy((void*)buffer, (void*)(initrd_address + node.offset), node.size); - return buffer; - } - - void* Read(char* filename) { - for (uint32_t i = 0; i < initrdHeader.fileCount; i++) { - if (nodes[i].filename == filename) - return (void*)(nodes[i].offset+(uintptr_t)initrd_address); - } - return 0; - } - - InitrdVolume::InitrdVolume(){ - strcpy(mountPoint.name, "initrd"); - mountPoint.flags = FS_NODE_DIRECTORY | FS_NODE_MOUNTPOINT; - - mountPoint.read = Initrd::Read; - mountPoint.write = Initrd::Write; - mountPoint.open = Initrd::Open; - mountPoint.close = Initrd::Close; - mountPoint.readDir = Initrd::ReadDir; - mountPoint.findDir = Initrd::FindDir; - - strcpy(mountPointDirent.name, "initrd"); - mountPointDirent.type = FS_NODE_DIRECTORY; - } - - size_t InitrdVolume::Read(struct fs_node* node, size_t offset, size_t size, uint8_t *buffer){ - return Initrd::Read(node, offset, size, buffer); - } - - size_t InitrdVolume::Write(struct fs_node* node, size_t offset, size_t size, uint8_t *buffer){ - return Initrd::Write(node, offset, size, buffer); - } - - void InitrdVolume::Open(struct fs_node* node, uint32_t flags){ - Initrd::Open(node, flags); - } - - void InitrdVolume::Close(struct fs_node* node){ - Initrd::Close(node); - } - - int InitrdVolume::ReadDir(struct fs_node* node, fs_dirent_t* dirent, uint32_t index){ - return Initrd::ReadDir(node, dirent, index); - } - - fs_node* InitrdVolume::FindDir(struct fs_node* node, char* name){ - return Initrd::FindDir(node, name); - } +/* + * + * Old Initrd Format, no longer used + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Initrd{ + int ReadDir(fs_node_t* node, fs_dirent_t* dirent, uint32_t index); + fs_node_t* FindDir(fs_node_t* node, char* name); + + size_t Read(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); + size_t ReadNull(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); + + void Open(fs_node_t* node, uint32_t flags); + void Close(fs_node_t* node); + + size_t Write(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer); + + lemoninitfs_header_t initrdHeader; + lemoninitfs_node_t* nodes; + fs_node_t* fsNodes; + + //fs_dirent_t dirent; + + void* initrd_address; + + InitrdVolume* vol; + + void Initialize(uintptr_t address, uint32_t size) { + #ifdef Lemon32 + void* virtual_address = (void*)Memory::KernelAllocateVirtualPages(size / PAGE_SIZE + 1); + Memory::MapVirtualPages(address, (uint32_t)virtual_address, size / PAGE_SIZE + 1); + initrd_address = virtual_address; + #endif + #ifdef Lemon64 + initrd_address = (void*)address; + #endif + Log::Info("Initrd address: "); + Log::Info(address); + Log::Info("Size:"); + Log::Info(size, false); + Log::Info("File Count:"); + Log::Info(*((uint32_t*)initrd_address), false); + Log::Write("files\r\n"); + initrdHeader = *(lemoninitfs_header_t*)initrd_address; + nodes = (lemoninitfs_node_t*)(initrd_address + sizeof(lemoninitfs_header_t)); + fsNodes = (fs_node_t*)kmalloc(sizeof(fs_node_t)*initrdHeader.fileCount); + + for(int i = 0; i < initrdHeader.fileCount; i++){ + fs_node_t* node = &(fsNodes[i]); + strcpy(node->name,nodes[i].filename); + node->inode = i; + node->flags = FS_NODE_FILE; + node->read = Initrd::Read; + node->write = Initrd::Write; + node->open = Initrd::Open; + node->close = Initrd::Close; + node->size = nodes[i].size; + } + + vol = new InitrdVolume(); + + fs::volumes->add_back(vol); + + InitrdVolume* vol2 = new InitrdVolume(); // Very Cheap Workaround + strcpy(vol2->mountPoint.name, "lib"); + strcpy(vol2->mountPointDirent.name, "lib"); + + fs::volumes->add_back(vol2); + } + + size_t Read(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer){ + lemoninitfs_node_t inode = nodes[node->inode]; + + if(offset > inode.size) return 0; + else if(offset + size > inode.size || size > inode.size) size = inode.size - offset; + + if(!size) return 0; + + memcpy(buffer, (void*)((uintptr_t)inode.offset + (uintptr_t)initrd_address + offset), size); + return size; + } + + size_t Write(fs_node_t* node, size_t offset, size_t size, uint8_t *buffer){ + return 0; // It's a ramdisk. + } + + void Open(fs_node_t* node, uint32_t flags){ + + } + + void Close(fs_node_t* node){ + + } + + int ReadDir(fs_node_t* node, fs_dirent_t* dirent, uint32_t index){ + if(index >= initrdHeader.fileCount + 2) return -1; + + if(index == 0) { + memset(dirent->name,0,128); // Zero the string + strcpy(dirent->name,"."); + dirent->inode = 0; + dirent->type = FS_NODE_DIRECTORY; + return 0; + } else if (index == 1){ + memset(dirent->name,0,128); // Zero the string + strcpy(dirent->name,".."); + dirent->inode = 2; + dirent->type = FS_NODE_DIRECTORY; + return 0; + } + memset(dirent->name,0,128); // Zero the string + strcpy(dirent->name,nodes[index - 2].filename); + dirent->inode = index - 3; + dirent->type = 0; + + return 0; + } + + fs_node_t* FindDir(fs_node_t* node, char* name) { + for(int i = 0; i < initrdHeader.fileCount;i++){ + if(strcmp(fsNodes[i].name,name) == 0) return &(fsNodes[i]); + } + + if(strcmp(".", name) == 0) return node; + if(strcmp("..", name) == 0) return fs::GetRoot(); + + return NULL; + } + + + lemoninitfs_node_t* List() { + return nodes; + } + + lemoninitfs_header_t* GetHeader() { + return &initrdHeader; + } + + void* Read(int node) { + return (void*)(nodes[node].offset+(uintptr_t)initrd_address); + } + + uint8_t* Read(lemoninitfs_node_t node, uint8_t* buffer) { + memcpy((void*)buffer, (void*)(initrd_address + node.offset), node.size); + return buffer; + } + + void* Read(char* filename) { + for (uint32_t i = 0; i < initrdHeader.fileCount; i++) { + if (nodes[i].filename == filename) + return (void*)(nodes[i].offset+(uintptr_t)initrd_address); + } + return 0; + } + + InitrdVolume::InitrdVolume(){ + strcpy(mountPoint.name, "initrd"); + mountPoint.flags = FS_NODE_DIRECTORY | FS_NODE_MOUNTPOINT; + + mountPoint.read = Initrd::Read; + mountPoint.write = Initrd::Write; + mountPoint.open = Initrd::Open; + mountPoint.close = Initrd::Close; + mountPoint.readDir = Initrd::ReadDir; + mountPoint.findDir = Initrd::FindDir; + + strcpy(mountPointDirent.name, "initrd"); + mountPointDirent.type = FS_NODE_DIRECTORY; + } + + size_t InitrdVolume::Read(struct fs_node* node, size_t offset, size_t size, uint8_t *buffer){ + return Initrd::Read(node, offset, size, buffer); + } + + size_t InitrdVolume::Write(struct fs_node* node, size_t offset, size_t size, uint8_t *buffer){ + return Initrd::Write(node, offset, size, buffer); + } + + void InitrdVolume::Open(struct fs_node* node, uint32_t flags){ + Initrd::Open(node, flags); + } + + void InitrdVolume::Close(struct fs_node* node){ + Initrd::Close(node); + } + + int InitrdVolume::ReadDir(struct fs_node* node, fs_dirent_t* dirent, uint32_t index){ + return Initrd::ReadDir(node, dirent, index); + } + + fs_node* InitrdVolume::FindDir(struct fs_node* node, char* name){ + return Initrd::FindDir(node, name); + } } \ No newline at end of file diff --git a/Kernel/src/gpt.cpp b/Kernel/src/gpt.cpp index dcd4d914..9829582f 100755 --- a/Kernel/src/gpt.cpp +++ b/Kernel/src/gpt.cpp @@ -1,57 +1,57 @@ -#include - -#include -#include -#include -#include - -#include - -namespace GPT{ - int Parse(DiskDevice* disk){ - gpt_header_t* header = (gpt_header_t*)kmalloc(disk->blocksize); - - if(int e = disk->ReadDiskBlock(1, disk->blocksize, (uint8_t*)header); e){ - Log::Info("[GPT] Disk error %d", e); - return -1; // Disk Error - } - - if(header->signature != GPT_HEADER_SIGNATURE /*Check Signature*/ || header->partNum == 0 /*Make sure there is at least 1 partition*/){ - return 0; // GPT not present or corrupted - } - - if(debugLevelPartitions >= DebugLevelNormal){ - Log::Info("Found GPT Header Partitions: "); - Log::Write(header->partNum); - Log::Write(" Entry Size:"); - Log::Write(header->partEntrySize); - } - - uint64_t tableLBA = header->partitionTableLBA; - - int partNum = 4;//header->partNum; - - gpt_entry_t* partitionTable = (gpt_entry_t*)kmalloc(partNum * header->partEntrySize); - if(disk->ReadDiskBlock(tableLBA,partNum * header->partEntrySize,(uint8_t*)partitionTable)){ - return -1; // Disk Error - } - - for(int i = 0; i < partNum; i++){ - gpt_entry_t entry = partitionTable[i]; - - if(debugLevelPartitions >= DebugLevelNormal){ - Log::Info("Found GPT Partition of size %d MB", (entry.endLBA - entry.startLBA) * 512 / 1024 / 1024); - } - - if((entry.endLBA - entry.startLBA)){ - PartitionDevice* part = new PartitionDevice(entry.startLBA, entry.endLBA, disk); - disk->partitions.add_back(part); - DeviceManager::RegisterDevice(*part); - } - } - - kfree(partitionTable); - kfree(header); - return partNum; - } +#include + +#include +#include +#include +#include + +#include + +namespace GPT{ + int Parse(DiskDevice* disk){ + gpt_header_t* header = (gpt_header_t*)kmalloc(disk->blocksize); + + if(int e = disk->ReadDiskBlock(1, disk->blocksize, (uint8_t*)header); e){ + Log::Info("[GPT] Disk error %d", e); + return -1; // Disk Error + } + + if(header->signature != GPT_HEADER_SIGNATURE /*Check Signature*/ || header->partNum == 0 /*Make sure there is at least 1 partition*/){ + return 0; // GPT not present or corrupted + } + + if(debugLevelPartitions >= DebugLevelNormal){ + Log::Info("Found GPT Header Partitions: "); + Log::Write(header->partNum); + Log::Write(" Entry Size:"); + Log::Write(header->partEntrySize); + } + + uint64_t tableLBA = header->partitionTableLBA; + + int partNum = 4;//header->partNum; + + gpt_entry_t* partitionTable = (gpt_entry_t*)kmalloc(partNum * header->partEntrySize); + if(disk->ReadDiskBlock(tableLBA,partNum * header->partEntrySize,(uint8_t*)partitionTable)){ + return -1; // Disk Error + } + + for(int i = 0; i < partNum; i++){ + gpt_entry_t entry = partitionTable[i]; + + if(debugLevelPartitions >= DebugLevelNormal){ + Log::Info("Found GPT Partition of size %d MB", (entry.endLBA - entry.startLBA) * 512 / 1024 / 1024); + } + + if((entry.endLBA - entry.startLBA)){ + PartitionDevice* part = new PartitionDevice(entry.startLBA, entry.endLBA, disk); + disk->partitions.add_back(part); + DeviceManager::RegisterDevice(*part); + } + } + + kfree(partitionTable); + kfree(header); + return partNum; + } } \ No newline at end of file diff --git a/Kernel/src/liballoc/_liballoc.cpp b/Kernel/src/liballoc/_liballoc.cpp index e946c2dc..aa39b773 100755 --- a/Kernel/src/liballoc/_liballoc.cpp +++ b/Kernel/src/liballoc/_liballoc.cpp @@ -1,57 +1,57 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -volatile int liballocLock = 0; - -extern "C" { - -int liballoc_lock() { - while(acquireTestLock(&liballocLock)) { - //assert(CheckInterrupts()); - } // If for some reason liballoc is locked before the scheduler starts something probably went horribly wrong - return 0; -} - -int liballoc_unlock() { - releaseLock(&liballocLock); - return 0; -} - -void liballoc_kprintf(const char* __restrict fmt, ...){ - va_list args; - va_start(args, fmt); - Log::WriteF(fmt, args); - va_end(args); -} - -void* liballoc_alloc(size_t pages) { - void* addr = (void*)Memory::KernelAllocate4KPages(pages); - for (size_t i = 0; i < pages; i++) - { - uint64_t phys = Memory::AllocatePhysicalMemoryBlock(); - Memory::KernelMapVirtualMemory4K(phys, (uint64_t)addr + i * PAGE_SIZE_4K, 1); - } - - memset(addr, 0, pages * PAGE_SIZE_4K); - - return addr; -} - -int liballoc_free(void* addr, size_t pages) { - for(size_t i = 0; i < pages; i++){ - uint64_t phys = Memory::VirtualToPhysicalAddress((uintptr_t)addr + i); - Memory::FreePhysicalMemoryBlock(phys); - } - Memory::KernelFree4KPages(addr, pages); - return 0; -} - + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +volatile int liballocLock = 0; + +extern "C" { + +int liballoc_lock() { + while(acquireTestLock(&liballocLock)) { + //assert(CheckInterrupts()); + } // If for some reason liballoc is locked before the scheduler starts something probably went horribly wrong + return 0; +} + +int liballoc_unlock() { + releaseLock(&liballocLock); + return 0; +} + +void liballoc_kprintf(const char* __restrict fmt, ...){ + va_list args; + va_start(args, fmt); + Log::WriteF(fmt, args); + va_end(args); +} + +void* liballoc_alloc(size_t pages) { + void* addr = (void*)Memory::KernelAllocate4KPages(pages); + for (size_t i = 0; i < pages; i++) + { + uint64_t phys = Memory::AllocatePhysicalMemoryBlock(); + Memory::KernelMapVirtualMemory4K(phys, (uint64_t)addr + i * PAGE_SIZE_4K, 1); + } + + memset(addr, 0, pages * PAGE_SIZE_4K); + + return addr; +} + +int liballoc_free(void* addr, size_t pages) { + for(size_t i = 0; i < pages; i++){ + uint64_t phys = Memory::VirtualToPhysicalAddress((uintptr_t)addr + i); + Memory::FreePhysicalMemoryBlock(phys); + } + Memory::KernelFree4KPages(addr, pages); + return 0; +} + } \ No newline at end of file diff --git a/Kernel/src/net/socket.cpp b/Kernel/src/net/socket.cpp index ba453286..ae514622 100755 --- a/Kernel/src/net/socket.cpp +++ b/Kernel/src/net/socket.cpp @@ -1,447 +1,447 @@ -#include - -#include -#include -#include -#include - -Socket* Socket::CreateSocket(int domain, int type, int protocol){ - if(type & SOCK_NONBLOCK) type &= ~SOCK_NONBLOCK; - - if(domain != UnixDomain && domain != InternetProtocol){ - Log::Warning("CreateSocket: domain %d is not supported", domain); - return nullptr; - } - if(type != StreamSocket && type != DatagramSocket){ - Log::Warning("CreateSocket: type %d is not supported", type); - return nullptr; - } - if(protocol){ - Log::Warning("CreateSocket: protocol is ignored"); - } - - if(domain == UnixDomain){ - return new LocalSocket(type, protocol); - } else if (domain == InternetProtocol){ - if(type == DatagramSocket){ - return new UDPSocket(type, protocol); - } - } - - return nullptr; -} - -Socket::Socket(int type, int protocol){ - this->type = type; - flags = FS_NODE_SOCKET; -} - -Socket::~Socket(){ - if(bound){ - SocketManager::DestroySocket(this); - } -} - -Socket* Socket::Accept(sockaddr* addr, socklen_t* addrlen){ - return Accept(addr, addrlen, 0); -} - -Socket* Socket::Accept(sockaddr* addr, socklen_t* addrlen, int mode){ - assert(!"Accept has been called from socket base"); - - return nullptr; -} - -int Socket::Bind(const sockaddr* addr, socklen_t addrlen){ - assert(!"Bind has been called from socket base"); - - return -1; -} - -int Socket::Connect(const sockaddr* addr, socklen_t addrlen){ - assert(!"Connect has been called from socket base"); - - return -1; -} - -int Socket::Listen(int backlog){ - return 0; -} - -ssize_t Socket::Read(size_t offset, size_t size, uint8_t* buffer){ - return Receive(buffer, size, 0); -} - -int64_t Socket::Receive(void* buffer, size_t len, int flags){ - if(!connected) {} - - return ReceiveFrom(buffer, len, flags, nullptr, nullptr); -} - -int64_t Socket::ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen){ - assert(!"ReceiveFrom has been called from socket base"); - - return -1; // We should not return but get the compiler to shut up -} - -ssize_t Socket::Write(size_t offset, size_t size, uint8_t* buffer){ - return Send(buffer, size, 0); -} - -int64_t Socket::Send(void* buffer, size_t len, int flags){ - return SendTo(buffer, len, flags, nullptr, 0); -} - -int64_t Socket::SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen){ - assert(!"SendTo has been called from socket base"); - - return -1; // We should not return but get the compiler to shut up -} - -fs_fd_t* Socket::Open(size_t flags){ - fs_fd_t* fDesc = (fs_fd_t*)kmalloc(sizeof(fs_fd_t)); - - fDesc->pos = 0; - fDesc->mode = flags; - fDesc->node = this; - - return fDesc; -} - -void Socket::Close(){ - if(bound){ - SocketManager::DestroySocket(this); - } - - if(handleCount == 0) - delete this; -} - -void Socket::Watch(FilesystemWatcher& watcher, int events){ - assert(!"Socket::Watch called from socket base"); -} - -void Socket::Unwatch(FilesystemWatcher& watcher){ - assert(!"Socket::Unwatch called from socket base"); -} - -LocalSocket::LocalSocket(int type, int protocol) : Socket(type, protocol){ - domain = UnixDomain; - flags = FS_NODE_SOCKET; - - assert(type == StreamSocket || type == DatagramSocket); -} - -int LocalSocket::ConnectTo(Socket* client){ - assert(passive); - - pendingConnections.Wait(); - - pending.add_back(client); - - acquireLock(&watcherLock); - while(watching.get_length()){ - watching.remove_at(0)->Signal(); - } - releaseLock(&watcherLock); - - while(!client->connected){ - // TODO: Actually block the task - Scheduler::Yield(); - } - - pendingConnections.Signal(); - - return 0; -} - -void LocalSocket::DisconnectPeer(){ - assert(peer); - - peer->OnDisconnect(); - - peer = nullptr; -} - -void LocalSocket::OnDisconnect(){ - connected = false; - - acquireLock(&watcherLock); - while(watching.get_length()){ - watching.remove_at(0)->Signal(); // Signal all watching on disconnect - } - releaseLock(&watcherLock); - - peer = nullptr; -} - -Socket* LocalSocket::Accept(sockaddr* addr, socklen_t* addrlen, int mode){ - if((mode & O_NONBLOCK) && pending.get_length() <= 0){ - return nullptr; - } - - while(pending.get_length() <= 0){ - // TODO: Actually block the task - //Log::Info("polling"); - Scheduler::Yield(); - } - - Socket* next = pending.remove_at(0); - assert(next->GetDomain() == UnixDomain); - - LocalSocket* client = (LocalSocket*) next; - - LocalSocket* sock = new LocalSocket(*client); - sock->outbound = client->inbound; // Outbound to client - sock->inbound = client->outbound; // Inbound to server - sock->role = ServerRole; - sock->peer = client; - client->peer = sock; - - sock->connected = client->connected = true; - - return sock; -} - -int LocalSocket::Bind(const sockaddr* addr, socklen_t addrlen){ - if(addr->family != UnixDomain){ - Log::Info("Bind: Socket is not a UNIX domain socket"); - return -EAFNOSUPPORT; - } - - if(addrlen > sizeof(sockaddr_un)){ - Log::Info("Bind: Invalid address length"); - return -EINVAL; - } - - if(bound){ - Log::Info("Bind: Socket already bound"); - return -EINVAL; - } - - if(SocketManager::BindSocket(this, addr, addrlen)) { - Log::Info("Bind: Address in use"); - return -EADDRINUSE; - } - - bound = true; - - return 0; -} - -int LocalSocket::Connect(const sockaddr* addr, socklen_t addrlen){ - if(addr->family != UnixDomain){ - Log::Info("Connect: Socket is not a UNIX domain socket"); - return -EAFNOSUPPORT; - } - - if(addrlen > sizeof(sockaddr_un)){ - Log::Info("Connect: Invalid address length"); - return -EINVAL; - } - - if(connected){ - Log::Info("Connect: Already connected"); - return -EISCONN; - } - - if(passive){ - Log::Info("Connect: Cannot connect on a listen socket"); - return -EOPNOTSUPP; - } - - if (type == DatagramSocket){ - inbound = new PacketStream(); - outbound = new PacketStream(); - } else { - inbound = new DataStream(1024); - outbound = new DataStream(1024); - } - - role = ClientRole; - - Socket* sock = SocketManager::ResolveSocketAddress(addr, addrlen); - if(!(sock && sock->IsListening())){ // Make sure the socket is both present and listening - Log::Warning("Socket Not Found"); - return -ECONNREFUSED; - } - - if(sock->GetDomain() != UnixDomain){ - return -ENOSYS; - } - - ((LocalSocket*)sock)->ConnectTo(this); - - return 0; -} - -int LocalSocket::Listen(int backlog){ - acquireLock(&slock); - pendingConnections.SetValue(backlog + 1); - passive = true; - - if(inbound) { - delete inbound; - inbound = nullptr; - } - - if(outbound) { - delete outbound; - outbound = nullptr; - } - - releaseLock(&slock); - return 0; -} - -int64_t LocalSocket::ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen){ - if(type == StreamSocket){ - if(src || addrlen){ - return -EISCONN; - } - } else if (type == DatagramSocket){ - if(src || addrlen){ - return -EOPNOTSUPP; - } - } - - if(!inbound){ - Log::Warning("LocalSocket not connected"); - return -ENOTCONN; - } - - if(inbound->Empty() && (flags & MSG_DONTWAIT)){ - return -EAGAIN; - } else while(inbound->Empty()){ - inbound->Wait(); - } - - if(flags & MSG_PEEK){ - return inbound->Peek(buffer, len); - } else { - return inbound->Read(buffer, len); - } -} - -int64_t LocalSocket::SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen){ - if(type == StreamSocket){ - if(src || addrlen){ - return -EISCONN; - } - } else if (type == DatagramSocket){ - if(src || addrlen){ - return -EOPNOTSUPP; - } - } - - if(!connected){ - Log::Warning("LocalSocket not connected"); - return -ENOTCONN; - } - - if(type == StreamSocket && (flags & MSG_DONTWAIT) && outbound->Pos() + len >= STREAM_MAX_BUFSIZE){ - return -EAGAIN; - } else while(type == StreamSocket && outbound->Pos() + len >= STREAM_MAX_BUFSIZE) { - Scheduler::Yield(); - } - - int64_t written = outbound->Write(buffer, len); - - if(peer && peer->CanRead()){ - acquireLock(&peer->watcherLock); - while(peer->watching.get_length()){ - peer->watching.remove_at(0)->Signal(); - } - releaseLock(&peer->watcherLock); - } - - return written; -} - -fs_fd_t* LocalSocket::Open(size_t flags){ - fs_fd_t* fDesc = (fs_fd_t*)kmalloc(sizeof(fs_fd_t)); - - fDesc->pos = 0; - fDesc->mode = flags; - fDesc->node = this; - - handleCount++; - - return fDesc; -} - -void LocalSocket::Close(){ - if(peer){ - DisconnectPeer(); - } - - Socket::Close(); -} - -void LocalSocket::Watch(FilesystemWatcher& watcher, int events){ - if(!(events & (POLLIN | POLLPRI))){ - return; - } - - if(CanRead() | !IsConnected()){ // POLLHUP does not care if it is requested - return; - } - - acquireLock(&watcherLock); - watching.add_back(&watcher); - releaseLock(&watcherLock); -} - -void LocalSocket::Unwatch(FilesystemWatcher& watcher){ - acquireLock(&watcherLock); - watching.remove(&watcher); - releaseLock(&watcherLock); -} - -namespace SocketManager{ - List sockets; - - Socket* ResolveSocketAddress(const sockaddr* addr, socklen_t addrlen){ - char address[addrlen + 1]; - strncpy(address, addr->data, addrlen); - address[addrlen] = 0; - - for(unsigned i = 0; i < sockets.get_length(); i++){ - if(strcmp(sockets.get_at(i).address, address) == 0){ - return sockets.get_at(i).socket; - } - } - - return nullptr; - } - - int BindSocket(Socket* sock, const sockaddr* addr, socklen_t addrlen){ - char* address = (char*)kmalloc(addrlen + 1); - strncpy(address, addr->data, addrlen); - address[addrlen] = 0; - - for(unsigned i = 0; i < sockets.get_length(); i++){ - if(strcmp(sockets.get_at(i).address, address) == 0) { - kfree(address); - return -1; // Address in use - } - } - - SocketBinding binding; - binding.address = address; - binding.socket = sock; - - sockets.add_back(binding); - - return 0; - } - - void DestroySocket(Socket* sock){ - for(unsigned i = 0; i < sockets.get_length(); i++){ - if(sockets[i].socket == sock) { - kfree(sockets[i].address); - sockets.remove_at(i); - } - } - } +#include + +#include +#include +#include +#include + +Socket* Socket::CreateSocket(int domain, int type, int protocol){ + if(type & SOCK_NONBLOCK) type &= ~SOCK_NONBLOCK; + + if(domain != UnixDomain && domain != InternetProtocol){ + Log::Warning("CreateSocket: domain %d is not supported", domain); + return nullptr; + } + if(type != StreamSocket && type != DatagramSocket){ + Log::Warning("CreateSocket: type %d is not supported", type); + return nullptr; + } + if(protocol){ + Log::Warning("CreateSocket: protocol is ignored"); + } + + if(domain == UnixDomain){ + return new LocalSocket(type, protocol); + } else if (domain == InternetProtocol){ + if(type == DatagramSocket){ + return new UDPSocket(type, protocol); + } + } + + return nullptr; +} + +Socket::Socket(int type, int protocol){ + this->type = type; + flags = FS_NODE_SOCKET; +} + +Socket::~Socket(){ + if(bound){ + SocketManager::DestroySocket(this); + } +} + +Socket* Socket::Accept(sockaddr* addr, socklen_t* addrlen){ + return Accept(addr, addrlen, 0); +} + +Socket* Socket::Accept(sockaddr* addr, socklen_t* addrlen, int mode){ + assert(!"Accept has been called from socket base"); + + return nullptr; +} + +int Socket::Bind(const sockaddr* addr, socklen_t addrlen){ + assert(!"Bind has been called from socket base"); + + return -1; +} + +int Socket::Connect(const sockaddr* addr, socklen_t addrlen){ + assert(!"Connect has been called from socket base"); + + return -1; +} + +int Socket::Listen(int backlog){ + return 0; +} + +ssize_t Socket::Read(size_t offset, size_t size, uint8_t* buffer){ + return Receive(buffer, size, 0); +} + +int64_t Socket::Receive(void* buffer, size_t len, int flags){ + if(!connected) {} + + return ReceiveFrom(buffer, len, flags, nullptr, nullptr); +} + +int64_t Socket::ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen){ + assert(!"ReceiveFrom has been called from socket base"); + + return -1; // We should not return but get the compiler to shut up +} + +ssize_t Socket::Write(size_t offset, size_t size, uint8_t* buffer){ + return Send(buffer, size, 0); +} + +int64_t Socket::Send(void* buffer, size_t len, int flags){ + return SendTo(buffer, len, flags, nullptr, 0); +} + +int64_t Socket::SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen){ + assert(!"SendTo has been called from socket base"); + + return -1; // We should not return but get the compiler to shut up +} + +fs_fd_t* Socket::Open(size_t flags){ + fs_fd_t* fDesc = (fs_fd_t*)kmalloc(sizeof(fs_fd_t)); + + fDesc->pos = 0; + fDesc->mode = flags; + fDesc->node = this; + + return fDesc; +} + +void Socket::Close(){ + if(bound){ + SocketManager::DestroySocket(this); + } + + if(handleCount == 0) + delete this; +} + +void Socket::Watch(FilesystemWatcher& watcher, int events){ + assert(!"Socket::Watch called from socket base"); +} + +void Socket::Unwatch(FilesystemWatcher& watcher){ + assert(!"Socket::Unwatch called from socket base"); +} + +LocalSocket::LocalSocket(int type, int protocol) : Socket(type, protocol){ + domain = UnixDomain; + flags = FS_NODE_SOCKET; + + assert(type == StreamSocket || type == DatagramSocket); +} + +int LocalSocket::ConnectTo(Socket* client){ + assert(passive); + + pendingConnections.Wait(); + + pending.add_back(client); + + acquireLock(&watcherLock); + while(watching.get_length()){ + watching.remove_at(0)->Signal(); + } + releaseLock(&watcherLock); + + while(!client->connected){ + // TODO: Actually block the task + Scheduler::Yield(); + } + + pendingConnections.Signal(); + + return 0; +} + +void LocalSocket::DisconnectPeer(){ + assert(peer); + + peer->OnDisconnect(); + + peer = nullptr; +} + +void LocalSocket::OnDisconnect(){ + connected = false; + + acquireLock(&watcherLock); + while(watching.get_length()){ + watching.remove_at(0)->Signal(); // Signal all watching on disconnect + } + releaseLock(&watcherLock); + + peer = nullptr; +} + +Socket* LocalSocket::Accept(sockaddr* addr, socklen_t* addrlen, int mode){ + if((mode & O_NONBLOCK) && pending.get_length() <= 0){ + return nullptr; + } + + while(pending.get_length() <= 0){ + // TODO: Actually block the task + //Log::Info("polling"); + Scheduler::Yield(); + } + + Socket* next = pending.remove_at(0); + assert(next->GetDomain() == UnixDomain); + + LocalSocket* client = (LocalSocket*) next; + + LocalSocket* sock = new LocalSocket(*client); + sock->outbound = client->inbound; // Outbound to client + sock->inbound = client->outbound; // Inbound to server + sock->role = ServerRole; + sock->peer = client; + client->peer = sock; + + sock->connected = client->connected = true; + + return sock; +} + +int LocalSocket::Bind(const sockaddr* addr, socklen_t addrlen){ + if(addr->family != UnixDomain){ + Log::Info("Bind: Socket is not a UNIX domain socket"); + return -EAFNOSUPPORT; + } + + if(addrlen > sizeof(sockaddr_un)){ + Log::Info("Bind: Invalid address length"); + return -EINVAL; + } + + if(bound){ + Log::Info("Bind: Socket already bound"); + return -EINVAL; + } + + if(SocketManager::BindSocket(this, addr, addrlen)) { + Log::Info("Bind: Address in use"); + return -EADDRINUSE; + } + + bound = true; + + return 0; +} + +int LocalSocket::Connect(const sockaddr* addr, socklen_t addrlen){ + if(addr->family != UnixDomain){ + Log::Info("Connect: Socket is not a UNIX domain socket"); + return -EAFNOSUPPORT; + } + + if(addrlen > sizeof(sockaddr_un)){ + Log::Info("Connect: Invalid address length"); + return -EINVAL; + } + + if(connected){ + Log::Info("Connect: Already connected"); + return -EISCONN; + } + + if(passive){ + Log::Info("Connect: Cannot connect on a listen socket"); + return -EOPNOTSUPP; + } + + if (type == DatagramSocket){ + inbound = new PacketStream(); + outbound = new PacketStream(); + } else { + inbound = new DataStream(1024); + outbound = new DataStream(1024); + } + + role = ClientRole; + + Socket* sock = SocketManager::ResolveSocketAddress(addr, addrlen); + if(!(sock && sock->IsListening())){ // Make sure the socket is both present and listening + Log::Warning("Socket Not Found"); + return -ECONNREFUSED; + } + + if(sock->GetDomain() != UnixDomain){ + return -ENOSYS; + } + + ((LocalSocket*)sock)->ConnectTo(this); + + return 0; +} + +int LocalSocket::Listen(int backlog){ + acquireLock(&slock); + pendingConnections.SetValue(backlog + 1); + passive = true; + + if(inbound) { + delete inbound; + inbound = nullptr; + } + + if(outbound) { + delete outbound; + outbound = nullptr; + } + + releaseLock(&slock); + return 0; +} + +int64_t LocalSocket::ReceiveFrom(void* buffer, size_t len, int flags, sockaddr* src, socklen_t* addrlen){ + if(type == StreamSocket){ + if(src || addrlen){ + return -EISCONN; + } + } else if (type == DatagramSocket){ + if(src || addrlen){ + return -EOPNOTSUPP; + } + } + + if(!inbound){ + Log::Warning("LocalSocket not connected"); + return -ENOTCONN; + } + + if(inbound->Empty() && (flags & MSG_DONTWAIT)){ + return -EAGAIN; + } else while(inbound->Empty()){ + inbound->Wait(); + } + + if(flags & MSG_PEEK){ + return inbound->Peek(buffer, len); + } else { + return inbound->Read(buffer, len); + } +} + +int64_t LocalSocket::SendTo(void* buffer, size_t len, int flags, const sockaddr* src, socklen_t addrlen){ + if(type == StreamSocket){ + if(src || addrlen){ + return -EISCONN; + } + } else if (type == DatagramSocket){ + if(src || addrlen){ + return -EOPNOTSUPP; + } + } + + if(!connected){ + Log::Warning("LocalSocket not connected"); + return -ENOTCONN; + } + + if(type == StreamSocket && (flags & MSG_DONTWAIT) && outbound->Pos() + len >= STREAM_MAX_BUFSIZE){ + return -EAGAIN; + } else while(type == StreamSocket && outbound->Pos() + len >= STREAM_MAX_BUFSIZE) { + Scheduler::Yield(); + } + + int64_t written = outbound->Write(buffer, len); + + if(peer && peer->CanRead()){ + acquireLock(&peer->watcherLock); + while(peer->watching.get_length()){ + peer->watching.remove_at(0)->Signal(); + } + releaseLock(&peer->watcherLock); + } + + return written; +} + +fs_fd_t* LocalSocket::Open(size_t flags){ + fs_fd_t* fDesc = (fs_fd_t*)kmalloc(sizeof(fs_fd_t)); + + fDesc->pos = 0; + fDesc->mode = flags; + fDesc->node = this; + + handleCount++; + + return fDesc; +} + +void LocalSocket::Close(){ + if(peer){ + DisconnectPeer(); + } + + Socket::Close(); +} + +void LocalSocket::Watch(FilesystemWatcher& watcher, int events){ + if(!(events & (POLLIN | POLLPRI))){ + return; + } + + if(CanRead() | !IsConnected()){ // POLLHUP does not care if it is requested + return; + } + + acquireLock(&watcherLock); + watching.add_back(&watcher); + releaseLock(&watcherLock); +} + +void LocalSocket::Unwatch(FilesystemWatcher& watcher){ + acquireLock(&watcherLock); + watching.remove(&watcher); + releaseLock(&watcherLock); +} + +namespace SocketManager{ + List sockets; + + Socket* ResolveSocketAddress(const sockaddr* addr, socklen_t addrlen){ + char address[addrlen + 1]; + strncpy(address, addr->data, addrlen); + address[addrlen] = 0; + + for(unsigned i = 0; i < sockets.get_length(); i++){ + if(strcmp(sockets.get_at(i).address, address) == 0){ + return sockets.get_at(i).socket; + } + } + + return nullptr; + } + + int BindSocket(Socket* sock, const sockaddr* addr, socklen_t addrlen){ + char* address = (char*)kmalloc(addrlen + 1); + strncpy(address, addr->data, addrlen); + address[addrlen] = 0; + + for(unsigned i = 0; i < sockets.get_length(); i++){ + if(strcmp(sockets.get_at(i).address, address) == 0) { + kfree(address); + return -1; // Address in use + } + } + + SocketBinding binding; + binding.address = address; + binding.socket = sock; + + sockets.add_back(binding); + + return 0; + } + + void DestroySocket(Socket* sock){ + for(unsigned i = 0; i < sockets.get_length(); i++){ + if(sockets[i].socket == sock) { + kfree(sockets[i].address); + sockets.remove_at(i); + } + } + } } \ No newline at end of file diff --git a/Kernel/src/storage/diskdevice.cpp b/Kernel/src/storage/diskdevice.cpp index f19d626b..a7b63539 100755 --- a/Kernel/src/storage/diskdevice.cpp +++ b/Kernel/src/storage/diskdevice.cpp @@ -1,83 +1,83 @@ -#include - -#include -#include -#include -#include - -static int nextDeviceNumber = 0; - -DiskDevice::DiskDevice() : Device(TypeDiskDevice){ - flags = FS_NODE_CHARDEVICE; - - char buf[16]; - strcpy(buf, "hd"); - itoa(nextDeviceNumber++, buf + 2, 10); - - SetName(buf); -} - -int DiskDevice::InitializePartitions(){ - static char letter = 'a'; - for(unsigned i = 0; i < partitions.get_length(); i++){ - if(fs::FAT32::Identify(partitions.get_at(i)) > 0) { - char vname[] = {'h', 'd', letter++, 0}; - auto vol = new fs::FAT32::Fat32Volume(partitions.get_at(i),vname); - fs::volumes->add_back(vol); - } else if(fs::Ext2::Identify(partitions.get_at(i)) > 0) { - bool systemFound = false; - - for(auto& vol : *fs::volumes){ // First Ext2 partition is mounted as /system - if(strcmp(vol->mountPointDirent.name, "system") == 0){ - systemFound = true; // System partition found - } - } - - fs::Ext2::Ext2Volume* vol = nullptr; - - if(systemFound){ - char vname[] = {'h', 'd', letter++, 0}; - vol = new fs::Ext2::Ext2Volume(partitions.get_at(i), vname); - } else { - vol = new fs::Ext2::Ext2Volume(partitions.get_at(i), "system"); - } - - if(!vol->Error()) - fs::volumes->add_back(vol); - else - delete vol; - } - } - - return 0; -} - -int DiskDevice::ReadDiskBlock(uint64_t lba, uint32_t count, void* buffer){ - return -1; -} - -int DiskDevice::WriteDiskBlock(uint64_t lba, uint32_t count, void* buffer){ - return -1; -} - -ssize_t DiskDevice::Read(size_t off, size_t size, uint8_t* buffer){ - if(off % blocksize){ - return -EINVAL; // Block aligned reads only - } - - int e = ReadDiskBlock(off / blocksize, size, buffer); - - if(e){ - return -EIO; - } - - return size; -} - -ssize_t DiskDevice::Write(size_t off, size_t size, uint8_t* buffer){ - return -ENOSYS; -} - -DiskDevice::~DiskDevice(){ - +#include + +#include +#include +#include +#include + +static int nextDeviceNumber = 0; + +DiskDevice::DiskDevice() : Device(TypeDiskDevice){ + flags = FS_NODE_CHARDEVICE; + + char buf[16]; + strcpy(buf, "hd"); + itoa(nextDeviceNumber++, buf + 2, 10); + + SetName(buf); +} + +int DiskDevice::InitializePartitions(){ + static char letter = 'a'; + for(unsigned i = 0; i < partitions.get_length(); i++){ + if(fs::FAT32::Identify(partitions.get_at(i)) > 0) { + char vname[] = {'h', 'd', letter++, 0}; + auto vol = new fs::FAT32::Fat32Volume(partitions.get_at(i),vname); + fs::volumes->add_back(vol); + } else if(fs::Ext2::Identify(partitions.get_at(i)) > 0) { + bool systemFound = false; + + for(auto& vol : *fs::volumes){ // First Ext2 partition is mounted as /system + if(strcmp(vol->mountPointDirent.name, "system") == 0){ + systemFound = true; // System partition found + } + } + + fs::Ext2::Ext2Volume* vol = nullptr; + + if(systemFound){ + char vname[] = {'h', 'd', letter++, 0}; + vol = new fs::Ext2::Ext2Volume(partitions.get_at(i), vname); + } else { + vol = new fs::Ext2::Ext2Volume(partitions.get_at(i), "system"); + } + + if(!vol->Error()) + fs::volumes->add_back(vol); + else + delete vol; + } + } + + return 0; +} + +int DiskDevice::ReadDiskBlock(uint64_t lba, uint32_t count, void* buffer){ + return -1; +} + +int DiskDevice::WriteDiskBlock(uint64_t lba, uint32_t count, void* buffer){ + return -1; +} + +ssize_t DiskDevice::Read(size_t off, size_t size, uint8_t* buffer){ + if(off % blocksize){ + return -EINVAL; // Block aligned reads only + } + + int e = ReadDiskBlock(off / blocksize, size, buffer); + + if(e){ + return -EIO; + } + + return size; +} + +ssize_t DiskDevice::Write(size_t off, size_t size, uint8_t* buffer){ + return -ENOSYS; +} + +DiskDevice::~DiskDevice(){ + } \ No newline at end of file diff --git a/Kernel/src/storage/partitiondevice.cpp b/Kernel/src/storage/partitiondevice.cpp index dd0931f9..7a79c947 100755 --- a/Kernel/src/storage/partitiondevice.cpp +++ b/Kernel/src/storage/partitiondevice.cpp @@ -1,50 +1,50 @@ -#include - -#include - -PartitionDevice::PartitionDevice(uint64_t startLBA, uint64_t endLBA, DiskDevice* disk) : Device(TypePartitionDevice){ - this->startLBA = startLBA; - this->endLBA = endLBA; - this->parentDisk = disk; - - flags = FS_NODE_BLKDEVICE; - - char buf[18]; - strcpy(buf, parentDisk->GetName()); - strcat(buf, "p"); - itoa(parentDisk->nextPartitionNumber++, buf + strlen(buf), 10); - - SetName(buf); -} - -int PartitionDevice::ReadAbsolute(uint64_t offset, uint32_t count, void* buffer){ - if(offset + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; - - uint64_t lba = offset / parentDisk->blocksize; - uint64_t tempCount = offset + (offset % parentDisk->blocksize); // Account for that we read from start of block - uint8_t buf[tempCount]; - - if(int e = ReadBlock(lba, parentDisk->blocksize, buf)){ - return e; - } - - memcpy(buffer, buf + (offset % parentDisk->blocksize), count); - - return 0; -} - -int PartitionDevice::ReadBlock(uint64_t lba, uint32_t count, void* buffer){ - if(lba * parentDisk->blocksize + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; - - return parentDisk->ReadDiskBlock(lba + startLBA, count, buffer); -} - -int PartitionDevice::WriteBlock(uint64_t lba, uint32_t count, void* buffer){ - if(lba * parentDisk->blocksize + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; - - return parentDisk->WriteDiskBlock(lba + startLBA, count, buffer); -} - -PartitionDevice::~PartitionDevice(){ - +#include + +#include + +PartitionDevice::PartitionDevice(uint64_t startLBA, uint64_t endLBA, DiskDevice* disk) : Device(TypePartitionDevice){ + this->startLBA = startLBA; + this->endLBA = endLBA; + this->parentDisk = disk; + + flags = FS_NODE_BLKDEVICE; + + char buf[18]; + strcpy(buf, parentDisk->GetName()); + strcat(buf, "p"); + itoa(parentDisk->nextPartitionNumber++, buf + strlen(buf), 10); + + SetName(buf); +} + +int PartitionDevice::ReadAbsolute(uint64_t offset, uint32_t count, void* buffer){ + if(offset + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; + + uint64_t lba = offset / parentDisk->blocksize; + uint64_t tempCount = offset + (offset % parentDisk->blocksize); // Account for that we read from start of block + uint8_t buf[tempCount]; + + if(int e = ReadBlock(lba, parentDisk->blocksize, buf)){ + return e; + } + + memcpy(buffer, buf + (offset % parentDisk->blocksize), count); + + return 0; +} + +int PartitionDevice::ReadBlock(uint64_t lba, uint32_t count, void* buffer){ + if(lba * parentDisk->blocksize + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; + + return parentDisk->ReadDiskBlock(lba + startLBA, count, buffer); +} + +int PartitionDevice::WriteBlock(uint64_t lba, uint32_t count, void* buffer){ + if(lba * parentDisk->blocksize + count > (endLBA - startLBA) * parentDisk->blocksize) return 2; + + return parentDisk->WriteDiskBlock(lba + startLBA, count, buffer); +} + +PartitionDevice::~PartitionDevice(){ + } \ No newline at end of file diff --git a/LibLemon/include/lemon/gui/window.h b/LibLemon/include/lemon/gui/window.h index ae2cef0f..8ee5024a 100755 --- a/LibLemon/include/lemon/gui/window.h +++ b/LibLemon/include/lemon/gui/window.h @@ -1,239 +1,239 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#define WINDOW_FLAGS_NODECORATION 0x1 -#define WINDOW_FLAGS_RESIZABLE 0x2 -#define WINDOW_FLAGS_NOSHELL 0x4 -#define WINDOW_FLAGS_TOOLTIP 0x8 - -#define WINDOW_MENUBAR_HEIGHT 20 - -namespace Lemon::GUI { - __attribute__((unused)) static const char* wmSocketAddress = "lemonwm"; - - typedef void(*WindowPaintHandler)(surface_t*); - typedef void(*MessageReceiveHandler)(); - typedef void(*EventCallback)(); - - enum { - WindowBufferReturn = 100, - WindowEvent = 101, - }; - - enum { - WMCxtEntryTypeCommand, - WMCxtEntryTypeDivider, - WMCxtEntryTypeExpand, - }; - - struct WindowBuffer { - uint64_t currentBuffer; - uint64_t buffer1Offset; - uint64_t buffer2Offset; - uint32_t drawing; // Is being drawn? - uint32_t dirty; // Does it need to be drawn? - }; - - enum WindowType { - Basic, - GUI, - }; - - using WindowMenu = std::pair>; - - class WindowMenuBar : public Widget{ - public: - std::vector items; - - void Paint(surface_t* surface); - void OnMouseDown(vector2i_t mousePos); - void OnMouseUp(vector2i_t mousePos); - void OnMouseMove(vector2i_t mousePos); - }; - - class Window : public WMClient{ - private: - WindowBuffer* windowBufferInfo; - uint8_t* buffer1; - uint8_t* buffer2; - uint64_t windowBufferKey; - - uint32_t flags; - - int windowType = WindowType::Basic; - - timespec lastClick; - - void UpdateGUITheme(const std::string& path); - public: - vector2i_t lastMousePos = {-1, -1}; - WindowMenuBar* menuBar = nullptr; - Container rootContainer; - surface_t surface = {0, 0, 32, nullptr}; - bool closed = false; // Set to true when close button pressed - - Window(const char* title, vector2i_t size, uint32_t flags = 0, int type = WindowType::Basic, vector2i_t pos = {20, 20}); - ~Window(); - - inline void InitializeShellConnection() const { WMClient::InitializeShellConnection(); } - - ///////////////////////////// - /// \brief Set title of window - /// - /// \param name Service name to be used, must be unique - ///////////////////////////// - inline void SetTitle(const std::string& title) const { WMClient::SetTitle(title); } - - ///////////////////////////// - /// \brief Relocate window - /// - /// Move the window to position (x, y) on screen - /// - /// \param pos New position of window - ///////////////////////////// - inline void Relocate(vector2i_t pos) const { WMClient::Relocate(pos.x, pos.y); } - - ///////////////////////////// - /// \brief Resize window - /// - /// Resize the window - /// - /// \param size New size of window - ///////////////////////////// - void Resize(vector2i_t size); - - ///////////////////////////// - /// \brief Minimize window - /// - /// Show/hide the window on screen - /// - /// \param minimized Whether to show/hide the window - ///////////////////////////// - inline void Minimize(bool minimized = true) const { WMClient::Minimize(minimized); } - - ///////////////////////////// - /// \brief Minimize a window - /// - /// Show/hide the specified window on screen - /// - /// \param windowID Window to show/hide - /// \param minimized Whether to show/hide the window - ///////////////////////////// - inline void Minimize(int windowID, bool minimized) const { WMClient::Minimize(windowID, minimized); } - - ///////////////////////////// - /// \brief Update window flags - /// - /// \param flags New Flags - ///////////////////////////// - void UpdateFlags(uint32_t flags); - - ///////////////////////////// - /// \brief Paint window - /// - /// Call OnPaint(), if relevant draw GUI Widgets, then swap the window buffers. - ///////////////////////////// - void Paint(); - - ///////////////////////////// - /// \brief Swap the window buffers - /// - /// Swap the window buffers, equivalent to Paint() on a Basic Window without OnPaint() - ///////////////////////////// - void SwapBuffers(); - - ///////////////////////////// - /// \brief Poll the window for events - /// - /// Fill ev with an event if an event has been found and return true, otherwise return false - /// - /// \param ev Reference to \a LemonEvent to fill - /// - /// \return true when an event has been received, false when there was no event - ///////////////////////////// - bool PollEvent(LemonEvent& ev); - - ///////////////////////////// - /// \brief Wait for an event - /// - /// Blocks the thread until an event has been recieved - ///////////////////////////// - void WaitEvent(); - - ///////////////////////////// - /// \brief Send event - /// - /// Send an event for the root container widget (and its children) to handle. - /// If the application decides to use the GUI they can pass events from PollEvent to here - /// - /// \param ev Event to send - ///////////////////////////// - void GUIHandleEvent(LemonEvent& ev); - - ///////////////////////////// - /// \brief Add a widget to the window - /// - /// Adds a widget to the list of widgets in the root container. Pointer should be valid until Widget is removed. - /// - /// \param w Pointer to widget - ///////////////////////////// - void AddWidget(Widget* w); - - ///////////////////////////// - /// \brief Remove a widget from the window - /// - /// Removes a widget to the list of widgets in the root container. Always do this first before destroying the Widget. - /// - /// \param w Pointer to widget - ///////////////////////////// - void RemoveWidget(Widget* w); - - ///////////////////////////// - /// \brief Display a context menu on screen - /// - /// Get the window manager to display a context menu on the screen. An EventWindowCommand will be returned if/when an item in the context menu is clicked. - /// When pos is {x: -1, y: -1} the context menu will be displayed around the location of the mouse cursor - /// - /// \param entries Entries (name and id pair) to display - /// \param pos Position of context menu - ///////////////////////////// - void DisplayContextMenu(const std::vector& entries, vector2i_t pos = {-1, -1}); - - ///////////////////////////// - /// \brief Initialize the window menu bar - /// - /// Creates MenuBar object and adjusts root container accordingly. - ///////////////////////////// - void CreateMenuBar(); - - void (*OnMenuCmd)(unsigned short, Window*) = nullptr; - - ///////////////////////////// - /// \brief Get Window Flags - /// - /// \return window flags - ///////////////////////////// - inline uint32_t GetFlags() const { return flags; } - - ///////////////////////////// - /// \brief Get Window Size - /// - /// \return window size - ///////////////////////////// - inline vector2i_t GetSize() const { return {surface.width, surface.height}; }; - - ///////////////////////////// - /// \brief OnPaint callback - /// - /// Called when Paint() is called. Is run \e before the widgets are painted and the window buffers are swapped - ///////////////////////////// - WindowPaintHandler OnPaint = nullptr; - }; +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#define WINDOW_FLAGS_NODECORATION 0x1 +#define WINDOW_FLAGS_RESIZABLE 0x2 +#define WINDOW_FLAGS_NOSHELL 0x4 +#define WINDOW_FLAGS_TOOLTIP 0x8 + +#define WINDOW_MENUBAR_HEIGHT 20 + +namespace Lemon::GUI { + __attribute__((unused)) static const char* wmSocketAddress = "lemonwm"; + + typedef void(*WindowPaintHandler)(surface_t*); + typedef void(*MessageReceiveHandler)(); + typedef void(*EventCallback)(); + + enum { + WindowBufferReturn = 100, + WindowEvent = 101, + }; + + enum { + WMCxtEntryTypeCommand, + WMCxtEntryTypeDivider, + WMCxtEntryTypeExpand, + }; + + struct WindowBuffer { + uint64_t currentBuffer; + uint64_t buffer1Offset; + uint64_t buffer2Offset; + uint32_t drawing; // Is being drawn? + uint32_t dirty; // Does it need to be drawn? + }; + + enum WindowType { + Basic, + GUI, + }; + + using WindowMenu = std::pair>; + + class WindowMenuBar : public Widget{ + public: + std::vector items; + + void Paint(surface_t* surface); + void OnMouseDown(vector2i_t mousePos); + void OnMouseUp(vector2i_t mousePos); + void OnMouseMove(vector2i_t mousePos); + }; + + class Window : public WMClient{ + private: + WindowBuffer* windowBufferInfo; + uint8_t* buffer1; + uint8_t* buffer2; + uint64_t windowBufferKey; + + uint32_t flags; + + int windowType = WindowType::Basic; + + timespec lastClick; + + void UpdateGUITheme(const std::string& path); + public: + vector2i_t lastMousePos = {-1, -1}; + WindowMenuBar* menuBar = nullptr; + Container rootContainer; + surface_t surface = {0, 0, 32, nullptr}; + bool closed = false; // Set to true when close button pressed + + Window(const char* title, vector2i_t size, uint32_t flags = 0, int type = WindowType::Basic, vector2i_t pos = {20, 20}); + ~Window(); + + inline void InitializeShellConnection() const { WMClient::InitializeShellConnection(); } + + ///////////////////////////// + /// \brief Set title of window + /// + /// \param name Service name to be used, must be unique + ///////////////////////////// + inline void SetTitle(const std::string& title) const { WMClient::SetTitle(title); } + + ///////////////////////////// + /// \brief Relocate window + /// + /// Move the window to position (x, y) on screen + /// + /// \param pos New position of window + ///////////////////////////// + inline void Relocate(vector2i_t pos) const { WMClient::Relocate(pos.x, pos.y); } + + ///////////////////////////// + /// \brief Resize window + /// + /// Resize the window + /// + /// \param size New size of window + ///////////////////////////// + void Resize(vector2i_t size); + + ///////////////////////////// + /// \brief Minimize window + /// + /// Show/hide the window on screen + /// + /// \param minimized Whether to show/hide the window + ///////////////////////////// + inline void Minimize(bool minimized = true) const { WMClient::Minimize(minimized); } + + ///////////////////////////// + /// \brief Minimize a window + /// + /// Show/hide the specified window on screen + /// + /// \param windowID Window to show/hide + /// \param minimized Whether to show/hide the window + ///////////////////////////// + inline void Minimize(int windowID, bool minimized) const { WMClient::Minimize(windowID, minimized); } + + ///////////////////////////// + /// \brief Update window flags + /// + /// \param flags New Flags + ///////////////////////////// + void UpdateFlags(uint32_t flags); + + ///////////////////////////// + /// \brief Paint window + /// + /// Call OnPaint(), if relevant draw GUI Widgets, then swap the window buffers. + ///////////////////////////// + void Paint(); + + ///////////////////////////// + /// \brief Swap the window buffers + /// + /// Swap the window buffers, equivalent to Paint() on a Basic Window without OnPaint() + ///////////////////////////// + void SwapBuffers(); + + ///////////////////////////// + /// \brief Poll the window for events + /// + /// Fill ev with an event if an event has been found and return true, otherwise return false + /// + /// \param ev Reference to \a LemonEvent to fill + /// + /// \return true when an event has been received, false when there was no event + ///////////////////////////// + bool PollEvent(LemonEvent& ev); + + ///////////////////////////// + /// \brief Wait for an event + /// + /// Blocks the thread until an event has been recieved + ///////////////////////////// + void WaitEvent(); + + ///////////////////////////// + /// \brief Send event + /// + /// Send an event for the root container widget (and its children) to handle. + /// If the application decides to use the GUI they can pass events from PollEvent to here + /// + /// \param ev Event to send + ///////////////////////////// + void GUIHandleEvent(LemonEvent& ev); + + ///////////////////////////// + /// \brief Add a widget to the window + /// + /// Adds a widget to the list of widgets in the root container. Pointer should be valid until Widget is removed. + /// + /// \param w Pointer to widget + ///////////////////////////// + void AddWidget(Widget* w); + + ///////////////////////////// + /// \brief Remove a widget from the window + /// + /// Removes a widget to the list of widgets in the root container. Always do this first before destroying the Widget. + /// + /// \param w Pointer to widget + ///////////////////////////// + void RemoveWidget(Widget* w); + + ///////////////////////////// + /// \brief Display a context menu on screen + /// + /// Get the window manager to display a context menu on the screen. An EventWindowCommand will be returned if/when an item in the context menu is clicked. + /// When pos is {x: -1, y: -1} the context menu will be displayed around the location of the mouse cursor + /// + /// \param entries Entries (name and id pair) to display + /// \param pos Position of context menu + ///////////////////////////// + void DisplayContextMenu(const std::vector& entries, vector2i_t pos = {-1, -1}); + + ///////////////////////////// + /// \brief Initialize the window menu bar + /// + /// Creates MenuBar object and adjusts root container accordingly. + ///////////////////////////// + void CreateMenuBar(); + + void (*OnMenuCmd)(unsigned short, Window*) = nullptr; + + ///////////////////////////// + /// \brief Get Window Flags + /// + /// \return window flags + ///////////////////////////// + inline uint32_t GetFlags() const { return flags; } + + ///////////////////////////// + /// \brief Get Window Size + /// + /// \return window size + ///////////////////////////// + inline vector2i_t GetSize() const { return {surface.width, surface.height}; }; + + ///////////////////////////// + /// \brief OnPaint callback + /// + /// Called when Paint() is called. Is run \e before the widgets are painted and the window buffers are swapped + ///////////////////////////// + WindowPaintHandler OnPaint = nullptr; + }; } \ No newline at end of file diff --git a/LibLemon/include/lemon/system/fb.h b/LibLemon/include/lemon/system/fb.h index 9df9c99d..73093a0b 100755 --- a/LibLemon/include/lemon/system/fb.h +++ b/LibLemon/include/lemon/system/fb.h @@ -1,17 +1,17 @@ -#pragma once - -#include - -#ifndef __lemon__ - #error "Lemon OS Only" -#endif - -typedef struct FBInfo{ - uint32_t width; // Resolution width - uint32_t height; // Resolution height - uint16_t bpp; // Resolution depth/bits per pixel - - uint32_t pitch; // Video mode pitch -} __attribute__((packed)) fb_info_t; - +#pragma once + +#include + +#ifndef __lemon__ + #error "Lemon OS Only" +#endif + +typedef struct FBInfo{ + uint32_t width; // Resolution width + uint32_t height; // Resolution height + uint16_t bpp; // Resolution depth/bits per pixel + + uint32_t pitch; // Video mode pitch +} __attribute__((packed)) fb_info_t; + volatile uint8_t* LemonMapFramebuffer(FBInfo& fbInfo); \ No newline at end of file diff --git a/LibLemon/include/lemon/system/util.h b/LibLemon/include/lemon/system/util.h index 37cfe713..5561cd71 100755 --- a/LibLemon/include/lemon/system/util.h +++ b/LibLemon/include/lemon/system/util.h @@ -1,70 +1,70 @@ -#pragma once - -#ifndef __lemon__ - #error "Lemon OS Only" -#endif - -#include -#include -#include - -#include -#include - -typedef struct { - uint64_t pid; // Process ID - - uint32_t threadCount; // Process Thread Count - - int32_t uid; // User ID - int32_t gid; // Group ID - - uint8_t state; // Process State - - char name[NAME_MAX]; // Process Name - - uint64_t runningTime; // Amount of time in seconds that the process has been running - uint64_t activeUs; - - uint64_t usedMem; // Used memory in KB -} lemon_process_info_t; - -namespace Lemon{ - ///////////////////////////// - /// \brief Yields CPU timeslice to next process - ///////////////////////////// - void Yield(); - - ///////////////////////////// - /// \brief Get information about process - /// - /// Fill a lemon_process_info struct with information about the process specified. - /// - /// \param pid Process ID - /// \param pInfo Reference to process info structure - /// - /// \return 0 on success, -1 on failure (errno is set) - ///////////////////////////// - int GetProcessInfo(uint64_t pid, lemon_process_info_t& pInfo); - - ///////////////////////////// - /// \brief Get information about next process - /// - /// Fill a lemon_process_info struct with information about the process specified. - /// - /// \param pid Pointer of previous process ID - /// \param pInfo Reference to process info structure - /// - /// \return 0 on success, 1 on end, -1 on failure (errno is set) - ///////////////////////////// - int GetNextProcessInfo(uint64_t* pid, lemon_process_info_t& pInfo); - - ///////////////////////////// - /// \brief Retrieve a list of all processes - /// - /// Fill a vector with information about all running processes - /// - /// \param list Reference to a std::vector - ///////////////////////////// - void GetProcessList(std::vector& list); +#pragma once + +#ifndef __lemon__ + #error "Lemon OS Only" +#endif + +#include +#include +#include + +#include +#include + +typedef struct { + uint64_t pid; // Process ID + + uint32_t threadCount; // Process Thread Count + + int32_t uid; // User ID + int32_t gid; // Group ID + + uint8_t state; // Process State + + char name[NAME_MAX]; // Process Name + + uint64_t runningTime; // Amount of time in seconds that the process has been running + uint64_t activeUs; + + uint64_t usedMem; // Used memory in KB +} lemon_process_info_t; + +namespace Lemon{ + ///////////////////////////// + /// \brief Yields CPU timeslice to next process + ///////////////////////////// + void Yield(); + + ///////////////////////////// + /// \brief Get information about process + /// + /// Fill a lemon_process_info struct with information about the process specified. + /// + /// \param pid Process ID + /// \param pInfo Reference to process info structure + /// + /// \return 0 on success, -1 on failure (errno is set) + ///////////////////////////// + int GetProcessInfo(uint64_t pid, lemon_process_info_t& pInfo); + + ///////////////////////////// + /// \brief Get information about next process + /// + /// Fill a lemon_process_info struct with information about the process specified. + /// + /// \param pid Pointer of previous process ID + /// \param pInfo Reference to process info structure + /// + /// \return 0 on success, 1 on end, -1 on failure (errno is set) + ///////////////////////////// + int GetNextProcessInfo(uint64_t* pid, lemon_process_info_t& pInfo); + + ///////////////////////////// + /// \brief Retrieve a list of all processes + /// + /// Fill a vector with information about all running processes + /// + /// \param list Reference to a std::vector + ///////////////////////////// + void GetProcessList(std::vector& list); } \ No newline at end of file diff --git a/LibLemon/meson.build b/LibLemon/meson.build index 90c8273b..0e065783 100755 --- a/LibLemon/meson.build +++ b/LibLemon/meson.build @@ -1,61 +1,61 @@ -project('LibLemon', default_options : ['cpp_std=c++17', 'optimization=0', 'warning_level=2', 'werror=true']) - -liblemon_include_dirs = [ - include_directories('include') -] - -add_languages('c', 'cpp') - -nasm = find_program('nasm') -asmg = generator(nasm, - output : '@BASENAME@.asm.o', - arguments : [ - '-f', 'elf64', - '-g', '-F', 'dwarf', '-w+gnu-elf-extensions', - '@INPUT@', - '-o', '@OUTPUT@']) - -liblemon_cpp_args = ['-Wno-write-strings', '-Wno-missing-braces', - '-fPIC', - '-m64' ] - -add_project_arguments(liblemon_cpp_args, language : ['c', 'cpp']) -cpp_files = [ - 'src/gfx/font.cpp', - 'src/gfx/bitmapfont.cpp', - 'src/gfx/graphics.cpp', - 'src/gfx/image.cpp', - 'src/gfx/surface.cpp', - 'src/gfx/text.cpp', - - 'src/ipc/message.cpp', - 'src/ipc/interface.cpp', - - 'src/gui/window.cpp', - 'src/gui/widgets.cpp', - 'src/gui/colours.cpp', - 'src/gui/fileview.cpp', - 'src/gui/filedialog.cpp', - 'src/gui/messagebox.cpp', - - 'src/shell/shell.cpp', - - 'src/cfgparser.cpp', - 'src/lexer.cpp', - 'src/json.cpp', - 'src/sha.cpp', -] - -asm_files = [ - 'src/gfx/sse2.asm', -] - -subdir('src/lemon') - -prefix = get_option('prefix') -install_subdir('include', install_dir: prefix) - -static_library('lemon', [asmg.process(asm_files), cpp_files], - include_directories : liblemon_include_dirs, - link_args: ['-lfreetype', '-lstdc++', '-lz', '-lpng'], - install: true) +project('LibLemon', default_options : ['cpp_std=c++17', 'optimization=0', 'warning_level=2', 'werror=true']) + +liblemon_include_dirs = [ + include_directories('include') +] + +add_languages('c', 'cpp') + +nasm = find_program('nasm') +asmg = generator(nasm, + output : '@BASENAME@.asm.o', + arguments : [ + '-f', 'elf64', + '-g', '-F', 'dwarf', '-w+gnu-elf-extensions', + '@INPUT@', + '-o', '@OUTPUT@']) + +liblemon_cpp_args = ['-Wno-write-strings', '-Wno-missing-braces', + '-fPIC', + '-m64' ] + +add_project_arguments(liblemon_cpp_args, language : ['c', 'cpp']) +cpp_files = [ + 'src/gfx/font.cpp', + 'src/gfx/bitmapfont.cpp', + 'src/gfx/graphics.cpp', + 'src/gfx/image.cpp', + 'src/gfx/surface.cpp', + 'src/gfx/text.cpp', + + 'src/ipc/message.cpp', + 'src/ipc/interface.cpp', + + 'src/gui/window.cpp', + 'src/gui/widgets.cpp', + 'src/gui/colours.cpp', + 'src/gui/fileview.cpp', + 'src/gui/filedialog.cpp', + 'src/gui/messagebox.cpp', + + 'src/shell/shell.cpp', + + 'src/cfgparser.cpp', + 'src/lexer.cpp', + 'src/json.cpp', + 'src/sha.cpp', +] + +asm_files = [ + 'src/gfx/sse2.asm', +] + +subdir('src/lemon') + +prefix = get_option('prefix') +install_subdir('include', install_dir: prefix) + +static_library('lemon', [asmg.process(asm_files), cpp_files], + include_directories : liblemon_include_dirs, + link_args: ['-lfreetype', '-lstdc++', '-lz', '-lpng'], + install: true) diff --git a/LibLemon/src/lemon/meson.build b/LibLemon/src/lemon/meson.build index 605a1533..cbdfac40 100755 --- a/LibLemon/src/lemon/meson.build +++ b/LibLemon/src/lemon/meson.build @@ -1,10 +1,10 @@ -cpp_files += files( - 'fb.cpp', - 'filesystem.cpp', - 'info.cpp', - 'itoa.cpp', - 'sharedmem.cpp', - 'util.cpp', - 'input.cpp', - 'waitable.cpp', +cpp_files += files( + 'fb.cpp', + 'filesystem.cpp', + 'info.cpp', + 'itoa.cpp', + 'sharedmem.cpp', + 'util.cpp', + 'input.cpp', + 'waitable.cpp', ) \ No newline at end of file diff --git a/Resources/montserratlicense.txt b/Resources/montserratlicense.txt index 7881887b..f435ed8b 100755 --- a/Resources/montserratlicense.txt +++ b/Resources/montserratlicense.txt @@ -1,93 +1,93 @@ -Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. +Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Resources/sourcecodeprolicense.txt b/Resources/sourcecodeprolicense.txt index 6f4c937e..366206f5 100755 --- a/Resources/sourcecodeprolicense.txt +++ b/Resources/sourcecodeprolicense.txt @@ -1,93 +1,93 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Scripts/lemon-crossfile.txt b/Scripts/lemon-crossfile.txt index 4f62db45..8363e89c 100755 --- a/Scripts/lemon-crossfile.txt +++ b/Scripts/lemon-crossfile.txt @@ -1,15 +1,15 @@ -[binaries] -c = 'lemon-clang' -cpp = 'lemon-clang++' -ar = 'x86_64-lemon-ar' -strip = 'x86_64-lemon-strip' -ld = 'x86_64-lemon-ld' - -[host_machine] -system = 'lemon' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' - -[paths] +[binaries] +c = 'lemon-clang' +cpp = 'lemon-clang++' +ar = 'x86_64-lemon-ar' +strip = 'x86_64-lemon-strip' +ld = 'x86_64-lemon-ld' + +[host_machine] +system = 'lemon' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[paths] prefix = '~/.local/share/lemon/sysroot/system' \ No newline at end of file diff --git a/System/meson.build b/System/meson.build index 9acbe157..14c42e5e 100644 --- a/System/meson.build +++ b/System/meson.build @@ -1,37 +1,37 @@ -project('Lemon System', - default_options : ['warning_level=2', 'cpp_std=c++2a', 'optimization=3', 'werror=true']) - -add_languages('c', 'cpp') - -lemond_src = [ - 'Lemond/main.cpp', -] - -lemonwm_src = [ - 'LemonWM/main.cpp', - 'LemonWM/window.cpp', - 'LemonWM/input.cpp', - 'LemonWM/compositor.cpp', - 'LemonWM/wm.cpp', -] - -netgov_src = [ - 'NetworkGovernor/main.cpp', -] - -login_src = [ - 'Login/main.cpp', -] - -fterm_src = [ - 'FTerm/main.cpp', - 'FTerm/input.cpp', -] - -add_project_arguments(['-Wno-write-strings', '-Wno-unused-parameter', '-Wno-missing-braces', '-Wno-missing-field-initializers'], language : 'cpp') - -executable('init.lef', lemond_src, link_args : ['-llemon'], install_dir : 'lemon/', install : true) -executable('lemonwm.lef', lemonwm_src, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install_dir : 'lemon/', install : true) -executable('netgov.lef', netgov_src, install_dir : 'lemon/', install : true) -executable('login.lef', login_src, link_args : ['-llemon', '-lfreetype'], install_dir : 'lemon/', install : true) -executable('fterm.lef', fterm_src, link_args : ['-llemon', '-lfreetype'], install_dir : meson.current_source_dir() + '/../Initrd', install : true) +project('Lemon System', + default_options : ['warning_level=2', 'cpp_std=c++2a', 'optimization=3', 'werror=true']) + +add_languages('c', 'cpp') + +lemond_src = [ + 'Lemond/main.cpp', +] + +lemonwm_src = [ + 'LemonWM/main.cpp', + 'LemonWM/window.cpp', + 'LemonWM/input.cpp', + 'LemonWM/compositor.cpp', + 'LemonWM/wm.cpp', +] + +netgov_src = [ + 'NetworkGovernor/main.cpp', +] + +login_src = [ + 'Login/main.cpp', +] + +fterm_src = [ + 'FTerm/main.cpp', + 'FTerm/input.cpp', +] + +add_project_arguments(['-Wno-write-strings', '-Wno-unused-parameter', '-Wno-missing-braces', '-Wno-missing-field-initializers'], language : 'cpp') + +executable('init.lef', lemond_src, link_args : ['-llemon'], install_dir : 'lemon/', install : true) +executable('lemonwm.lef', lemonwm_src, link_args : ['-llemon', '-lfreetype', '-lz', '-lpng'], install_dir : 'lemon/', install : true) +executable('netgov.lef', netgov_src, install_dir : 'lemon/', install : true) +executable('login.lef', login_src, link_args : ['-llemon', '-lfreetype'], install_dir : 'lemon/', install : true) +executable('fterm.lef', fterm_src, link_args : ['-llemon', '-lfreetype'], install_dir : meson.current_source_dir() + '/../Initrd', install : true)