fixing more stuff and adding more stuff

This commit is contained in:
Gregory Kenneth Bowne 2024-04-01 21:20:34 -07:00
parent 528fb00d49
commit 79edf9eb6e
22 changed files with 390 additions and 82 deletions

BIN
.vscode/browse.vc.db vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4,14 +4,9 @@ kernel_sector equ 1 ; Sector containing the kernel (adjust for your kernel's l
kernel_segments equ 4 ; Number of sectors to load (adjust for your kernel size)
kernel_load_address equ 0x1000 ; Memory address to load the kernel
; ... (Function prototypes and int_13h implementation copied from previous response)
; Function prototypes for readability
; (These functions are not strictly necessary in NASM, but improve code organization)
; Prototype for BIOS disk read interrupt (INT 13h)
void int_13h(unsigned int ah, unsigned int al, unsigned int dx, unsigned int ch, unsigned int cl, unsigned int bx);
; Function prototype for error handling or printing a message
void error_handler(const char *message);
void error_handler(const char *message)
; Main kernel loading code
mov bx, kernel_load_address ; Set load address

18
src/cpu/cpuid.asm Normal file
View File

@ -0,0 +1,18 @@
[bits 32]
global cpuid
cpuid:
; Input parameter in EAX register
mov eax, %edi
; Call CPUID instruction (clobbers EAX, EBX, ECX, EDX)
cpuid
; Return values in output registers
mov %esi, [esp + 4] ; eax (output)
mov %edx, [esp + 8] ; ebx (output)
mov %ecx, [esp + 12] ; ecx (output)
mov %edi, [esp + 16] ; edx (output)
ret

36
src/cpu/cpuid.c Normal file
View File

@ -0,0 +1,36 @@
#include "cpuid.h"
#include <stdint.h>
void cpuid(uint32_t code, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
asm volatile ("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (code));
}
void identify_cpu() {
uint32_t max_leaf;
uint32_t vendor_id[4];
uint32_t eax, ebx, ecx, edx;
// Get the maximum supported leaf value (CPUID function)
cpuid(0, &eax, &ebx, &ecx, &edx);
max_leaf = eax;
// Get the vendor ID string
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
vendor_id[0] = eax;
vendor_id[1] = ebx;
vendor_id[2] = ecx;
vendor_id[3] = edx;
// Print the vendor ID string (assuming ASCII characters)
printf("Vendor ID: %.4s%.4s\n", (char *)&vendor_id[0], (char *)&vendor_id[1]);
// Identify basic features based on CPUID information (optional, needs further logic)
// ... (code to check specific CPU features using max_leaf and additional CPUID calls) ...
printf("Maximum leaf value: %u\n", max_leaf);
}
int main() {
identify_cpu();
return 0;
}

7
src/cpu/cpuid.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef CPUID_H
#define CPUID_H
// Function prototypes for CPUID instruction
void cpuid(uint32_t code, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
#endif

BIN
src/drivers/io/io.bin Normal file

Binary file not shown.

View File

@ -15,8 +15,15 @@
LPT3: 0x3BC
*/
typedef enum {
IO_SUCCESS = 0,
IO_ERROR_PORT_NOT_READY,
IO_ERROR_PORT_UNAVAILABLE,
// Add more error codes as needed
} IOErrorCode;
// Function to initialize the ports before reading or writing
void io_init()
void io_init(uint16_t port)
{
// Initialize COM1 port (0x3F8) - You can add more port initializations here if needed

View File

@ -4,7 +4,7 @@
#include <stdint.h>
// Function to initialize the COM and LPT ports
void io_init();
void io_init(uint16_t port);
// Function to read from the COM port
char io_read_com();

View File

@ -22,14 +22,20 @@ static size_t keyboard_buffer_tail = 0;
void set_interrupt_vector(uint8_t vector, void (*handler)());
void enable_interrupt(uint8_t vector);
bool keyboard_buffer_full()
{
return (keyboard_buffer_head + 1) % KEYBOARD_BUFFER_SIZE == keyboard_buffer_tail;
}
void KeyboardInterruptHandler()
{
uint8_t scancode = inb(KEYBOARD_DATA_PORT);
if (!keyboard_buffer_full())
{uint8_t scancode = inb(KEYBOARD_DATA_PORT);
uint8_t keycode = translate_scancode_to_keycode(scancode);
// Add scancode to buffer
keyboard_buffer[keyboard_buffer_head] = scancode;
keyboard_buffer_head = (keyboard_buffer_head + 1) % KEYBOARD_BUFFER_SIZE;
}
}
// Function to translate the combined extended scancode (first byte + second byte)
@ -134,7 +140,30 @@ uint8_t translate_scancode_to_keycode(uint8_t scancode)
[0x51] = KEYCODE_PAGE_DOWN,
[0x52] = KEYCODE_INSERT,
[0x53] = KEYCODE_DELETE,
[0x54] = KEYCODE_HOME,
[0x55] = KEYCODE_UP,
[0x56] = KEYCODE_PAGE_UP,
[0x57] = KEYCODE_LEFT_CTRL_BREAK, // Handle Break key (adjust if needed)
[0x58] = KEYCODE_RIGHT_SHIFT,
[0x59] = KEYCODE_NUM_LOCK,
[0x5A] = KEYCODE_SCROLL_LOCK,
[0x5B] = KEYCODE_F7,
[0x5C] = KEYCODE_F8,
[0x5D] = KEYCODE_F9,
[0x5E] = KEYCODE_F10,
[0x5F] = KEYCODE_PAUSE, // Handle Pause key (adjust if needed)
[0x60] = KEYCODE_INSERT,
[0x61] = KEYCODE_DELETE,
[0x62] = KEYCODE_RIGHT,
[0x63] = KEYCODE_END,
[0x64] = KEYCODE_DOWN,
[0x65] = KEYCODE_PAGE_DOWN,
[0x66] = KEYCODE_F11,
[0x67] = KEYCODE_F12,
[0x68] = KEYCODE_UNKNOWN, // (unused)
[0x69] = KEYCODE_LED_NUM_LOCK, // Num Lock LED status
[0x6A] = KEYCODE_LED_CAPS_LOCK, // Caps Lock LED status
[0x6B] = KEYCODE_LED_SCROLL_LOCK
// ... (complete the rest based on the scancode table)
[0xE0] = 0, // Handle extended scancodes (e.g., Print Screen) separately
};

View File

@ -8,6 +8,7 @@ void KeyboardInterruptHandler();
void keyboard_init();
bool keyboard_buffer_empty();
bool keyboard_buffer_full();
uint8_t keyboard_read_scancode();
void set_interrupt_vector(uint8_t vector, void (*handler)());
void enable_interrupt(uint8_t vector);

View File

@ -1,3 +1,4 @@
#include "ne2000.h"
#include <stdint.h>
// NE2000 registers
@ -12,15 +13,15 @@
// ... more commands ...
// Write a value to a NE2000 register
void ne2000_write_reg(uint16_t base_addr, uint8_t reg, uint8_t value) {
volatile uint8_t *ne2000_reg = (volatile uint8_t *)(base_addr + reg);
*ne2000_reg = value;
void ne2000_write_reg(uint16_t base_addr, uint8_t reg, uint8_t value)
{
outb(base_addr + reg, value);
}
// Read a value from a NE2000 register
uint8_t ne2000_read_reg(uint16_t base_addr, uint8_t reg) {
volatile uint8_t *ne2000_reg = (volatile uint8_t *)(base_addr + reg);
return *ne2000_reg;
uint8_t ne2000_read_reg(uint16_t base_addr, uint8_t reg)
{
return inb(base_addr + reg);
}
// Initialize the NE2000 card

View File

@ -1,23 +1,26 @@
#ifndef NE2000_H
#define NE2000_H
#include <stdint.h>
// NE2000 registers
#define NE2000_COMMAND 0x00
#define NE2000_PSTART 0x01
#define NE2000_PSTOP 0x02
// ... more registers ...
// NE2000 commands
#define NE2000_CMD_START 0x02
#define NE2000_CMD_STOP 0x01
// ... more commands ...
// Function prototypes
void ne2000_write_reg(uint16_t base_addr, uint8_t reg, uint8_t value);
uint8_t ne2000_read_reg(uint16_t base_addr, uint8_t reg);
void ne2000_init(uint16_t base_addr);
// ... more function prototypes ...
#endif // NE2000_H
#ifndef NE2000_H
#define NE2000_H
#include <stdint.h>
uint8_t inb(uint16_t port);
void outb(uint16_t port, uint8_t value);
// NE2000 registers
#define NE2000_COMMAND 0x00
#define NE2000_PSTART 0x01
#define NE2000_PSTOP 0x02
// ... more registers ...
// NE2000 commands
#define NE2000_CMD_START 0x02
#define NE2000_CMD_STOP 0x01
// ... more commands ...
// Function prototypes
void ne2000_write_reg(uint16_t base_addr, uint8_t reg, uint8_t value);
uint8_t ne2000_read_reg(uint16_t base_addr, uint8_t reg);
void ne2000_init(uint16_t base_addr);
// ... more function prototypes ...
#endif // NE2000_H

View File

@ -1,3 +1,32 @@
/*
fat16 goes here
*/
#include "fat16.h"
#include <stdint.h>
#include "fat16_io.h"
// Implementation of read_sector and write_sector functions (replace with actual disk I/O)
int read_sector(uint32_t sector_number, void *buffer)
{
// ... (Code to read a sector from disk) ...
}
int write_sector(uint32_t sector_number, void *buffer)
{
return read_sector_from_disk(sector_number, buffer);
}
// Function to parse the boot sector (replace with actual parsing logic)
int parse_boot_sector(const char *device_name)
{
// ... (Read and parse boot sector information) ...
return 0; // Or error code
}
// Function to mount the FAT16 volume (replace with actual mounting logic)
int mount_fat16(const char *device_name)
{
if (parse_boot_sector(device_name) != 0)
{
return -1; // Error parsing boot sector
}
// ... (Additional mounting logic) ...
return 0;
}

View File

@ -1,3 +1,26 @@
/*
fat16 goes here
*/
#ifndef FAT16_H
#define FAT16_H
#include <stdint.h>
// Define constants for sector size, cluster size, etc. (replace with actual values)
#define SECTOR_SIZE 512
#define BYTES_PER_CLUSTER 4096 // Example: 8 sectors per cluster
// Define structures for FAT entry, directory entry, etc.
typedef struct
{
// ... (FAT entry fields) ...
} fat_entry_t;
typedef struct
{
// ... (Directory entry fields) ...
} directory_entry_t;
// Function prototypes for FAT operations
int read_sector(uint32_t sector_number, void *buffer);
int write_sector(uint32_t sector_number, void *buffer);
int mount_fat16(const char *device_name); // Mount the FAT16 volume
// ... (other function prototypes) ...
#endif

View File

@ -0,0 +1,50 @@
#include "fat16_io.h"
#include <stdint.h>
// I/O port addresses for IDE controller (replace with actual values if needed)
#define PRIMARY_DATA_REGISTER 0x1F0
#define PRIMARY_ERROR_REGISTER 0x1F1
#define PRIMARY_COMMAND_REGISTER 0x1F2
#define PRIMARY_SELECT_REGISTER 0x1F6
// Define bit masks for IDE commands
#define ATA_CMD_READ_SECTORS_WITHOUT_RETRIES 0x20
#define ATA_CMD_READ_SECTORS_WITH_RETRIES 0xC4
// Function to read a sector from disk
int read_sector(uint32_t sector_number, void *buffer)
{
// 1. Prepare for disk access
outb(PRIMARY_SELECT_REGISTER, 0x00); // Select primary IDE channel
// 2. Wait for controller to become ready
while ((inb(PRIMARY_STATUS_REGISTER) & 0x02) == 0)
{
} // Wait for BUSY bit to clear
// 3. Send read command with parameters
outb(PRIMARY_COMMAND_REGISTER, ATA_CMD_READ_SECTORS_WITHOUT_RETRIES); // Replace with retries if needed
outb(PRIMARY_ERROR_REGISTER, 0); // Features (usually set to 0)
outb(PRIMARY_SELECT_REGISTER, (sector_number & 0x0FF) | 0x80); // LBA low byte with LBA bit set
outb(PRIMARY_COMMAND_REGISTER, ((sector_number >> 8) & 0xFF)); // LBA mid byte
outb(PRIMARY_COMMAND_REGISTER, ((sector_number >> 16) & 0x0F) | 0xE0); // LBA high byte with select bit
outb(PRIMARY_COMMAND_REGISTER, 1); // Number of sectors to read (1 in this case)
// 4. Wait for data transfer to complete (replace with timeout if needed)
while ((inb(PRIMARY_STATUS_REGISTER) & 0x08) == 0)
{
} // Wait for DRQ bit to set
// 5. Read data from the data register
for (int i = 0; i < 512; ++i)
{
((uint8_t *)buffer)[i] = inb(PRIMARY_DATA_REGISTER);
}
// 6. Check for errors (optional, implement error handling)
if (inb(PRIMARY_STATUS_REGISTER) & 0x01)
{
return -1; // Error occurred
}
return 0; // Success
}

View File

@ -0,0 +1,19 @@
#ifndef FAT16_IO_H
#define FAT16_IO_H
#include <stdint.h>
// I/O port addresses for IDE controller (replace with actual values if needed)
#define PRIMARY_DATA_REGISTER 0x1F0
#define PRIMARY_ERROR_REGISTER 0x1F1
#define PRIMARY_COMMAND_REGISTER 0x1F2
#define PRIMARY_SELECT_REGISTER 0x1F6
// Define bit masks for IDE commands
#define ATA_CMD_READ_SECTORS_WITHOUT_RETRIES 0x20
#define ATA_CMD_READ_SECTORS_WITH_RETRIES 0xC4
// Function prototype for reading a sector from disk
int read_sector(uint32_t sector_number, void *buffer);
#endif // FAT16_IO_H

BIN
src/kernel/arch/x86/gdt.bin Normal file

Binary file not shown.

View File

@ -1,21 +1,32 @@
#ifndef IDT_H
#define IDT_H
#include "include/types.h"
// IDT entry structure
struct idt_entry
{
uint16_t base_lo; // Lower 16 bits of handler function address
uint16_t sel; // Kernel segment selector
uint8_t always0; // Always 0
uint8_t flags; // Flags
uint16_t base_hi; // Upper 16 bits of handler function address
} __attribute__((packed));
extern struct idt_entry idt[256];
// Initialize the IDT
void InitializeIDT();
#endif /* IDT_H */
#ifndef IDT_H
#define IDT_H
#include "include/types.h"
#define IDT_ENTRY_SIZE 16
#if IDT_ENTRY_SIZE != 16
#error "idt_entry structure size mismatch!"
#endif
// IDT entry structure
struct idt_entry
{
uint16_t base_lo; // Lower 16 bits of handler function address
uint16_t sel; // Kernel segment selector
uint8_t always0; // Always 0
uint8_t flags; // Flags
uint16_t base_hi; // Upper 16 bits of handler function address
} __attribute__((packed));
extern struct idt_entry idt[256];
// Initialize the IDT
void InitializeIDT();
extern void KeyboardInterruptHandler();
extern void TimerInterruptHandler();
extern void LoadIDT(struct idt_entry *entry);
#endif /* IDT_H */

View File

@ -4,37 +4,117 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define PAGE_SIZE 4096
typedef struct memory_region_t
{
void *start_address;
size_t size;
} memory_region_t;
// Array of allocated memory regions (example)
memory_region_t *allocated_regions;
size_t num_allocated_regions;
jmp_buf page_fault_buffer;
void DivideByZero()
{
// Add logic to handle Divide By Zero Exception
printf("Divide By Zero Exception\n");
printf("Divide By Zero Exception\n");
// Additional Exception Handling Logic:
// Example: Perform specific actions for Divide By Zero scenario
// - Log the exception to a file
FILE *logFile = fopen("error.log", "a");
if (logFile != NULL) {
fprintf(logFile, "Divide By Zero Exception occurred\n");
fclose(logFile);
}
// Additional Exception Handling Logic:
// Example: Perform specific actions for Divide By Zero scenario
// - Log the exception to a file
FILE *logFile = fopen("error.log", "a");
if (logFile != NULL)
{
fprintf(logFile, "Divide By Zero Exception occurred\n");
fclose(logFile);
}
// - Gracefully terminate the kernel
printf("Exiting kernel due to Divide By Zero Exception\n");
// - Gracefully terminate the kernel
printf("Exiting kernel due to Divide By Zero Exception\n");
exit(EXIT_FAILURE);
}
void DoubleFault()
{
// printf("Double Fault Exception");
printf("Double Fault Exception\n");
// Handle double fault exception (typically unrecoverable)
exit(EXIT_FAILURE);
}
void PageFault()
// Function to check if address is within allocated memory (example)
int IsAddressInRange(uint16_t address)
{
// printf("Page Fault Exception");
for (size_t i = 0; i < num_allocated_regions; ++i)
{
if ((address >= allocated_regions[i].start_address) &&
(address < (allocated_regions[i].start_address + allocated_regions[i].size)))
{
return 1;
}
}
return 0;
}
// Placeholder for loading page from disk (replace with actual implementation)
void LoadPageFromDisk(uint16_t fault_address, void *page_buffer)
{
// Implement logic to read page data from disk based on fault_address
// and store it in the provided page_buffer
printf("** Placeholder: Load page from disk (implementation needed) **\n");
}
// Placeholder for modifying paging tables (replace with actual implementation)
void NotifyCPUAboutPage(uint16_t fault_address)
{
// Implement logic to modify paging tables based on fault_address
// to point to the loaded page data
printf("** Placeholder: Modify paging tables (implementation needed) **\n");
}
void PageFault(uint16_t fault_address)
{
// 1. Identify the cause of the page fault
if (IsAddressInRange(fault_address))
{
// Address is within allocated memory, potentially a missing page
printf("Page fault for address 0x%x (potentially missing page)\n", fault_address);
// 2. Allocate memory for the page data (assuming OS doesn't handle this)
void *page_buffer = malloc(PAGE_SIZE); // Replace with actual page size
if (page_buffer == NULL)
{
printf("Failed to allocate memory for page data\n");
exit(EXIT_FAILURE);
}
// 3. Load the missing page from disk
LoadPageFromDisk(fault_address, page_buffer);
// 4. Inform the CPU that the page is now available
NotifyCPUAboutPage(fault_address);
// 5. Free the temporary page buffer (if applicable)
free(page_buffer);
// 6. Resume execution with longjmp
longjmp(page_fault_buffer, 1);
}
else
{
// Handle invalid memory access
printf("Invalid memory access at 0x%x\n", fault_address);
exit(EXIT_FAILURE); // Or perform alternative error handling
}
}
void GeneralProtectionFault()
{
// printf("General Protection Fault Exception");
printf("General Protection Fault Exception\n");
// Handle general protection fault exception (access violation)
exit(EXIT_FAILURE);
}

View File

@ -33,7 +33,6 @@ void *malloc(size_t size)
}
// Align the size to the word size for efficiency
size += sizeof(size_t) - 1;
size &= ~(sizeof(size_t) - 1);
// Search for a free block of sufficient size