diff --git a/README.md b/README.md index ce7a580..4348845 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Screenshot_20240826_160940](https://github.com/user-attachments/assets/a4d2af98-7c7e-4a7f-a64c-31b0325d99d7) +![BlankOSshowcase](https://github.com/user-attachments/assets/63aae4ae-1633-4981-875d-8e2627ccc25c) > [!WARNING] > The project is currently paused, after months of work around the subject. I've had enough for now, and I'll surely come back in some time to implement the more advanced stuff I had planned. For now, enjoy the latest alpha version. diff --git a/src/drivers/pci.c b/src/drivers/pci.c new file mode 100644 index 0000000..18d05b6 --- /dev/null +++ b/src/drivers/pci.c @@ -0,0 +1,103 @@ +// PCI bus driver implementation +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#include +#include "pci.h" +#include "../libc/stdio.h" + +static inline void outl(uint16_t port, uint32_t value) +{ + __asm__ volatile ("outl %0, %1" : : "a"(value), "Nd"(port)); +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t ret; + __asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +void pci_write_config_address(uint32_t address) +{ + outl(PCI_CONFIG_ADDRESS, address); +} + +uint32_t pci_read_config_data() +{ + return inl(PCI_CONFIG_DATA); +} + +uint32_t pci_config_address(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) +{ + return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC); +} + +uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) +{ + uint32_t address = pci_config_address(bus, device, function, offset); + pci_write_config_address(address); + return pci_read_config_data(); +} + +pci_device_t pci_get_device(uint8_t bus, uint8_t device, uint8_t function) +{ + pci_device_t dev; + + uint32_t reg0 = pci_read(bus, device, function, 0x00); // Vendor ID, Device ID + uint32_t reg2 = pci_read(bus, device, function, 0x08); // Class, Subclass, Prog IF, Revision + + dev.vendor_id = reg0 & 0xFFFF; + dev.device_id = (reg0 >> 16) & 0xFFFF; + dev.class_code = (reg2 >> 24) & 0xFF; + dev.subclass = (reg2 >> 16) & 0xFF; + dev.prog_if = (reg2 >> 8) & 0xFF; + dev.revision_id = reg2 & 0xFF; + dev.bus = bus; + dev.device = device; + dev.function = function; + + return dev; +} + +void scan_pci_bus() +{ + for (uint16_t bus = 0; bus < 256; bus++) { + for (uint8_t device = 0; device < 32; device++) { + for (uint8_t function = 0; function < 8; function++) { + pci_device_t dev = pci_get_device(bus, device, function); + + if (dev.vendor_id != 0xFFFF) { + + // Maybe put that in a database in initrd.tar? + char* vendor_string; + switch(dev.vendor_id) + { + case 0x8086: + vendor_string = "Intel Corporation"; + break; + case 0x1234: + vendor_string = "Brain Actuated Technologies"; + break; + default: + vendor_string = "Unknown"; + break; + } + + char* device_string; + switch(dev.device_id) + { + default: + device_string = "Unknown"; + break; + } + + printf("PCI Device found: Bus %u, Device %u, Function %u, Vendor ID: 0x%x (%s), Device ID: 0x%x (%s), Class: 0x%x\n", + dev.bus, dev.device, dev.function, dev.vendor_id, vendor_string, dev.device_id, device_string, dev.class_code); + } + } + } + } +} + diff --git a/src/drivers/pci.h b/src/drivers/pci.h new file mode 100644 index 0000000..d9483bb --- /dev/null +++ b/src/drivers/pci.h @@ -0,0 +1,29 @@ +// PCI bus driver implementation header +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#ifndef PCI_H +#define PCI_H + +#include + +#define PCI_CONFIG_ADDRESS 0xCF8 +#define PCI_CONFIG_DATA 0xCFC + +typedef struct +{ + uint16_t vendor_id; + uint16_t device_id; + uint8_t class_code; + uint8_t subclass; + uint8_t prog_if; + uint8_t revision_id; + uint8_t bus; + uint8_t device; + uint8_t function; +} pci_device_t; + +void scan_pci_bus(); + +#endif diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 5805abf..ac7f6c3 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -16,6 +16,7 @@ #include "kheap.h" #include "initrd.h" #include "../programs/programs.h" +#include "../libc/crypto.h" void kmain(multiboot2_info *mb_info) { diff --git a/src/kernel/shell.c b/src/kernel/shell.c index e9876f7..4635483 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -143,6 +143,8 @@ void shell_install() register_command("ls", program_ls); register_command("cat", program_cat); register_command("bmp", program_bmp); + register_command("lspci", program_lspci); + register_command("naval", program_navalbattle); for (;;) { diff --git a/src/kernel/system.c b/src/kernel/system.c index 5af9b8e..7c6561b 100644 --- a/src/kernel/system.c +++ b/src/kernel/system.c @@ -50,3 +50,4 @@ void panic() { for (;;); } + diff --git a/src/libc/string.h b/src/libc/string.h index 496950a..590d29a 100644 --- a/src/libc/string.h +++ b/src/libc/string.h @@ -12,5 +12,4 @@ char* strtok(char* str, const char* delimiter); int atoi(char* str); void strcat(char* dest, const char* src); - #endif diff --git a/src/programs/misc.c b/src/programs/misc.c index fd206fa..3a4ecca 100644 --- a/src/programs/misc.c +++ b/src/programs/misc.c @@ -10,6 +10,7 @@ #include "../drivers/ata.h" #include "../drivers/rtc.h" #include "../kernel/io.h" +#include "../drivers/pci.h" // Print a rainbow colorful text for testing @@ -73,7 +74,7 @@ void program_uptime() void program_help() { - printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\n"); + printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\n"); } // Panic @@ -143,3 +144,10 @@ void program_reboot() while (1) asm volatile("hlt"); } + +// List PCI buses and devices + +void program_lspci() +{ + scan_pci_bus(); +} diff --git a/src/programs/navalbattle.c b/src/programs/navalbattle.c new file mode 100644 index 0000000..ad6c898 --- /dev/null +++ b/src/programs/navalbattle.c @@ -0,0 +1,334 @@ +// Simplified naval battle game +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#include "navalbattle.h" +#include "../libc/stdio.h" +#include "../kernel/system.h" +#include "../kernel/kheap.h" +#include "../libc/string.h" +#include "../libc/crypto.h" +#include "../drivers/serial.h" + +// Porting problems: +// - Color printf? (Need to implement ANSI escape sequences). +// - Scanf? +// - Malloc? (proof of concept) + +void program_navalbattle() +{ + clear(); + + grid_t* grid[SIZE][SIZE]; + grid_t* enemyGrid[SIZE][SIZE]; + + init_battlefield(grid); + init_battlefield(enemyGrid); + + placing_ally_ships(grid); + puts("Now, time for the enemies to prepare...\n"); + placing_enemy_ships(enemyGrid); + + delay((rand()%MAX_WAIT_TIME)+10); + + puts("Here we go!\n"); + show_game_stats(grid, enemyGrid); + + do + { + ally_do_attack(enemyGrid); + enemy_do_attack(grid); + show_game_stats(grid, enemyGrid); + } while (check_victory(grid, enemyGrid) == 0); + + return; +} + +void init_battlefield(grid_t* grid[SIZE][SIZE]) +{ + for (size_t i=0; ix = i; + grid[i][j]->y = j; + grid[i][j]->role = 0; + grid[i][j]->state = -2; + } + } +} + +void show_ally_battlefield(grid_t* grid[SIZE][SIZE]) +{ + puts("\n*** Ally grid ***\n"); + puts(" 0 1 2 3 4 5\n"); + + for (size_t i=0; istate) + { + case -2: + roleChar = 32; // space + break; + case -1: + roleChar = 120; + break; + case 0: + roleChar = 79; + break; + case 1: + roleChar = 88; + break; + default: + printf("Error: bad value in grid at x=%d y=%d\n", grid[i][j]->x, grid[i][j]->y); + shell_install(); + break; + } + + if (j == SIZE-1) + { + printf("%c]", roleChar); + } else if (j == 0) { + printf("[%c|", roleChar); + } else { + printf("%c|", roleChar); + } + } + puts("\n"); + } +} + +void placing_ally_ships(grid_t* grid[SIZE][SIZE]) +{ + puts("==== Allied preparation phase =====\nPlease enter the positions for your ships, sir.\n"); + + for (size_t i=0; i= SIZE || posY < 0 || posY >= SIZE) + { + printf("Invalid position x=%d y=%d, please retry.\n", posX, posY); + } + if (grid[posX][posY]->role == 1) + { + printf("A ship is already in x=%d y=%d, please retry.\n", posX, posY); + } + } while (posX < 0 || posX >= SIZE || posY < 0 || posY >= SIZE || grid[posX][posY]->role == 1); + + grid[posX][posY]->role = 1; + grid[posX][posY]->state = 0; + } +} + +void placing_enemy_ships(grid_t* grid[SIZE][SIZE]) +{ + for (size_t i=0; irole != 0); + + grid[posX][posY]->role = 1; + grid[posX][posY]->state = 0; + } +} + +void show_enemy_battlefield(grid_t* grid[SIZE][SIZE]) +{ + puts("\n*** Enemy grid ***\n"); + puts(" 0 1 2 3 4 5\n"); + + for (size_t i=0; istate) + { + case -2: + case 0: + roleChar = 32; + break; + case -1: + roleChar = 120; + break; + case 1: + roleChar = 88; + break; + default: + printf("Error: bad value in battlefield at x=%d y=%d\n", grid[i][j]->x, grid[i][j]->y); + shell_install(); + break; + } + if (j == SIZE-1) + { + printf("%c]", roleChar); + } else if (j == 0) { + printf("[%c|", roleChar); + } else { + printf("%c|", roleChar); + } + } + puts("\n"); + } + puts("\n"); +} + +void show_remaining_boats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]) +{ + int allyShips = 0; + int enemyShips = 0; + + for (size_t i=0; istate == 0) + { + allyShips++; + } + + if (enemyGrid[i][j]->state == 0) + { + enemyShips++; + } + } + } + + printf("%d ally ships and %d enemy ships remaining.\n", allyShips, enemyShips); + allyShips >= enemyShips ? colorputs("The allies are in a good posture.\n", yellow, black) : colorputs("The allies are losing terrain...\n", salmon, black); +} + +void show_game_stats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]) +{ + clear(); + colorputs("\n\n\nShowing known information:\n\n", cyan, black); + show_ally_battlefield(allyGrid); + show_enemy_battlefield(enemyGrid); + show_remaining_boats(allyGrid, enemyGrid); +} + +void do_attack(grid_t* grid[SIZE][SIZE], int x, int y) +{ + switch(grid[x][y]->state) + { + case -2: // Untouched ocean + colorputs("The torpedo explodes in water. Missed.\n", orange, black); + grid[x][y]->state = -1; + delay(30); + break; + case -1: // Already hit ocean + colorputs("We already striked here, sir... Too late.\n", orange, black); + break; + case 0: // Ship + colorputs("Hit! Well done!\n", green, black); + grid[x][y]->state = 1; + delay(30); + break; + case 1: // Already hit ship + colorputs("Sir, we already sunk that ship... (looser)\n", orange, black); + break; + } +} + +void ally_do_attack(grid_t* enemyGrid[SIZE][SIZE]) +{ + int x = 0, y = 0; + colorputs("\n* Ally attack preparation *\n", blue, black); + do + { + // yes, x and y are inverted. + puts("X coord: "); + char input_buffer[BUFFER_SIZE]; + get_input(input_buffer, BUFFER_SIZE); + y = atoi(input_buffer); + + puts("\nY coord: "); + char input_buffer2[BUFFER_SIZE]; + get_input(input_buffer2, BUFFER_SIZE); + x = atoi(input_buffer2); + + puts("\n"); + + if (x < 0 || x >= SIZE || y < 0 || y >= SIZE) + { + puts("Sir, this zone is not in our operation area! Please retry.\n"); + } + } while (x < 0 || x >= SIZE || y < 0 || y >= SIZE); + + do_attack(enemyGrid, x, y); +} + +void enemy_do_attack(grid_t* allyGrid[SIZE][SIZE]) +{ + int x = 0, y = 0; + colorputs("\n* Enemies are preparing for attack, everyone take shelter! *\n", blue, black); + + do + { + x = rand() % SIZE; + y = rand() % SIZE; + } while (allyGrid[x][y]->state == -1 || allyGrid[x][y]->state == 1); + + delay((rand()%MAX_WAIT_TIME)+10); + do_attack(allyGrid, x, y); +} + +int check_victory(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]) +{ + int allyShips = 0; + int enemyShips = 0; + + for (size_t i=0; istate == 0) + { + allyShips++; + } + + if (enemyGrid[i][j]->state == 0) + { + enemyShips++; + } + } + } + + if (allyShips > 0 && enemyShips == 0) + { + colorputs("The allies have won! Congratulations, chief!\n", green, black); + return 1; + } else if (enemyShips > 0 && allyShips == 0) + { + colorputs("The ennemies have won.. We must retreat.\n", red, black); + return 1; + } + return 0; +} diff --git a/src/programs/navalbattle.h b/src/programs/navalbattle.h new file mode 100644 index 0000000..d75db9a --- /dev/null +++ b/src/programs/navalbattle.h @@ -0,0 +1,36 @@ +// Simplified naval battle game header +// Author: xamidev +// Licensed under the Unlicense. See the repo below. +// https://github.com/xamidev/blankos + +#ifndef NAVALBATTLE_H +#define NAVALBATTLE_H + +#include "../drivers/framebuffer.h" + +typedef struct +{ + int x; + int y; + int role; + int state; +} grid_t; + +#define SIZE 6 +#define BOATS 5 +#define MAX_WAIT_TIME 20 +#define BUFFER_SIZE 16 + +void init_battlefield(grid_t* grid[SIZE][SIZE]); +void show_ally_battlefield(grid_t* grid[SIZE][SIZE]); +void placing_ally_ships(grid_t* grid[SIZE][SIZE]); +void placing_enemy_ships(grid_t* grid[SIZE][SIZE]); +void show_enemy_battlefield(grid_t* grid[SIZE][SIZE]); +void show_remaining_boats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]); +void show_game_stats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]); +void do_attack(grid_t* grid[SIZE][SIZE], int x, int y); +void ally_do_attack(grid_t* enemyGrid[SIZE][SIZE]); +void enemy_do_attack(grid_t* allyGrid[SIZE][SIZE]); +int check_victory(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]); + +#endif diff --git a/src/programs/programs.h b/src/programs/programs.h index 11c799e..fca21de 100644 --- a/src/programs/programs.h +++ b/src/programs/programs.h @@ -14,7 +14,6 @@ void program_sysinfo(); void get_cpuid(); void get_meminfo(unsigned int multiboot_info_address); // to be fixed: cannot get full memory map (sysinfo -v) -void program_conway(); void program_cowsay(); void cowsay(); // Splash screen void program_pi(); @@ -39,5 +38,10 @@ void program_ls(); void program_cat(); void program_bmp(); +void program_lspci(); + +// Games +void program_navalbattle(); +void program_conway(); #endif