最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

assembly - Why does my custom OS get stuck in a boot loop with the message 'Booting from Hard Drive...'? - Stack

programmeradmin3浏览0评论

I'm currently trying to make my own OS (and pretty new to assembly and C). Here is the code (I know it's not finished at all)

bootloader.asm :

[bits 16]
 0x7C00

start:
    cli
    call EnableA20
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 1
    mov cr0, eax
    jmp 0x08:Protected

gdt_start:
    dq 0
    dq 0x00CF9A000000FFFF
    dq 0x00CF92000000FFFF 
gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start


EnableA20:
    in al, 0x64
.wait1:
    test al, 2
    jnz .wait1
    mov al, 0xD1
    out 0x64, al
.wait2:
    in al, 0x64
    test al, 2
    jnz .wait2
    mov al, 0xDF
    out 0x60, al
    ret

[bits 32]
Protected:
    mov ax, 0x10
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov esp, 0x90000
    jmp 0x1000:0x00000000
    jmp $

times 510 - ($ - $$) db 0
dw 0xAA55

kernel.c :

/*
INCLUDE
*/
#include "stdint.h"
#include "stdbool.h"
#include <stddef.h>


/*
DEFINE
*/

#define PIT_COMMAND 0x43
#define PIT_CHANNEL0 0x40
#define PIT_FREQUENCY 1193182

#define KEYBOARD_DATA_PORT 0x60
#define PIC_EOI 0x20  

#define MAX_COMMAND_LENGTH 256

/*
VARIABLE
*/
bool isPressed = false;
int table_length;
char CurrentCommand[MAX_COMMAND_LENGTH] = {0};
int CommandLength = 0;
unsigned char scancode;
volatile uint8_t timer_expired = 0;
int color = 0x0f;
int row = 0;

/*
IO FUNCTION
*/
static inline uint16_t inw(uint16_t port) {
    uint16_t value;
    __asm__ volatile ("inw %1, %0" : "=a"(value) : "d"(port));
    return value;
}

static inline void outw(uint16_t port, uint16_t value) {
    __asm__ volatile ("outw %0, %1" : : "a"(value), "d"(port));
}

unsigned char inb(unsigned short port) {
    unsigned char result;
    __asm__("inb %1, %0" : "=a"(result) : "dN"(port));
    return result;
}

void outb(unsigned short port, unsigned char value) {
    __asm__ volatile ("outb %0, %1" : : "a"(value), "dN"(port));
}

/*
IMPORTANT FUNCTION
*/

long strtol(const char *str, char **endptr, int base) {
    const char *s = str;
    long result = 0;
    int sign = 1;

    while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r' || *s == '\f' || *s == '\v') {
        s++;
    }

    if (*s == '-') {
        sign = -1;
        s++;
    } else if (*s == '+') {
        s++;
    }

    if (base == 0) {
        if (*s == '0') {
            if (*(s + 1) == 'x' || *(s + 1) == 'X') {
                base = 16;
                s += 2;
            } else {
                base = 8;
                s++;
            }
        } else {
            base = 10;
        }
    }

    if (base < 2 || base > 36) {
        if (endptr) *endptr = (char *)str;
        return 0;
    }

    while (*s) {
        int digit = 0;

        if (*s >= '0' && *s <= '9') {
            digit = *s - '0';
        } else if (*s >= 'a' && *s <= 'z') {
            digit = *s - 'a' + 10;
        } else if (*s >= 'A' && *s <= 'Z') {
            digit = *s - 'A' + 10;
        } else {
            break;
        }


        if (digit >= base) {
            break;
        }

        result = result * base + digit;
        s++;
    }

    result *= sign;

    if (endptr) {
        *endptr = (char *)s;
    }

    return result;
}

int strcmp(const char *s1, const char *s2) {
    while (*s1 && *s2 && *s1 == *s2) {
        s1++;
        s2++;
    }
    return *s1 - *s2;
}

int strlen(const char *str) {
    int len = 0;
    while (str[len]) len++;
    return len;
}

void memset(char *buffer, char value, int size) {
    for (int i = 0; i < size; i++) {
        buffer[i] = value;
    }
}

/*
VIDEO RELATED
*/

void RenderTextAt(const char* text, int x, int y, int color) {
    char* screen = (char*) 0xB8000;
    int index = (y * 80 + x) * 2;
    for (int i = 0; text[i] != '\0' && index < 80 * 25 * 2; i++) {
        screen[index] = text[i];
        screen[index + 1] = color;
        index += 2;
    }
}

void RenderText(const char* text, int color) {
    RenderTextAt(text,0,0,color);
}


void clear_screen() {
    char *video_memory = (char *)0xB8000;
    for (int i = 0; i < 80 * 25 * 2; i += 2) {
        video_memory[i] = ' ';
        video_memory[i + 1] = 0x07;
    }
}

void ClearRegion(int x, int y, int width, int height) {
    char* video_memory = (char*) 0xB8000;
    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            int index = ((y + row) * 80 + (x + col)) * 2;
            video_memory[index] = ' ';
            video_memory[index + 1] = 0x07;
        }
    }
}

/*
TIME REALTED
*/
void timer_isr() {
    timer_expired = 1;
    outb(0x20, PIC_EOI);
}


void sleep(uint32_t milliseconds) {
    uint32_t ticks = milliseconds * (PIT_FREQUENCY / 1000);
    outb(PIT_COMMAND, 0x36);
    outb(PIT_CHANNEL0, ticks & 0xFF);
    outb(PIT_CHANNEL0, (ticks >> 8) & 0xFF);
    __asm__ volatile ("sti");
    timer_expired = 0;
    while (!timer_expired) {
        __asm__ volatile ("hlt");
    }
    __asm__ volatile ("cli");
}

/*
INPUT RELATED
*/
typedef struct {
    const char cle;
    const char* value;
} ScancodeTable;

ScancodeTable FR[] = {
    {0x0E, "BS"}, {0x1C, "Enter"}, {0x10, "a"}, {0x30, "b"}, {0x2E, "c"}, {0x20, "d"},
    {0x12, "e"}, {0x21, "f"}, {0x22, "g"}, {0x23, "h"}, {0x17, "i"}, {0x24, "j"},
    {0x25, "k"}, {0x26, "l"}, {0x27, "m"}, {0x31, "n"}, {0x18, "o"}, {0x19, "p"},
    {0x1E, "q"}, {0x13, "r"}, {0x1F, "s"}, {0x14, "t"}, {0x16, "u"}, {0x2F, "v"},
    {0x2C, "w"}, {0x2D, "x"}, {0x15, "y"}, {0x11, "z"}
};

const char* getKey(ScancodeTable table[], unsigned char code) {
    for (int i = 0; i < table_length; i++) {
        if (table[i].cle == code) {
            return table[i].value;
        }
    }
    return NULL;
}

void keyboard_interrupt_handler() {
    scancode = inb(KEYBOARD_DATA_PORT);
    if (!(scancode & 0x80)) {
        isPressed = true;
    }
    outb(0x20, PIC_EOI);
}

/*
ACPI AND SHUTDOWN RELATED
*/
struct RSDPDescriptor {
    char Signature[8];   
    uint8_t Checksum;
    char OEMID[6];
    uint8_t Revision;
    uint32_t RsdtAddress; 
} __attribute__((packed));

struct FADT {
    char Signature[4];    
    uint32_t Length;
    uint8_t Unused[76];
    uint32_t PM1aControlBlock;
    uint32_t PM1bControlBlock;
} __attribute__((packed));

void acpi_shutdown() {
    uint16_t pm1a_control = 0xB004;
    outw(pm1a_control, 0x2000);
}


/*
ROOT COMMAND
*/

void setcolor(){
    RenderTextAt("Code ? Ignore 0x", 0, row, color);
        row += 1;
        while (!isPressed);
        isPressed = 0;
        const char* key = getKey(FR, scancode);
        if (!key || strlen(key) != 1) {
            RenderTextAt("Invalid argument", 0, row, 0x04);
            return;
        }
        char key1 = key[0];
        RenderTextAt(&key1, 0, row, color);

        while (!isPressed);
        isPressed = 0;
        const char* key2 = getKey(FR, scancode);
        if (!key2 || strlen(key2) != 1) {
            RenderTextAt("Invalid argument", 0, row, 0x04);
            return;
        }
        char key2_char = key2[0];
        RenderTextAt(&key2_char, 1, row, color);

        char result[3] = {key1, key2_char, '\0'};
        color = (int)strtol(result, NULL, 16);
        row += 1;
}


/*
COMMAND HANDLING
*/
void RunCommand(const char* command, int length) {
    if (length == 0) return;

    if (strcmp(command, "clear") == 0) {
        clear_screen();
        row = 0;
    } else if (strcmp(command, "setcolor") == 0) {
        setcolor();
    } else if(strcmp(command,"shutdown") == 0) {
        acpi_shutdown();
    }else{
        RenderTextAt("Unknown command", 0, row, 0x04);
    }
    CommandLength = 0;
    memset(CurrentCommand, 0, MAX_COMMAND_LENGTH);
}

/*
MAIN
*/
void kernel_main() {
    table_length = sizeof(FR) / sizeof(ScancodeTable);
    RenderText("myOS", 0x0F);
    sleep(2000);
    clear_screen();
    while (1) {
        if (isPressed) {
            isPressed = 0;
            const char* LastChar = getKey(FR, scancode);
            if (LastChar != NULL) {
                if (strcmp(LastChar, "BS") == 0) {
                    if (CommandLength > 0) {
                        CommandLength--;
                        CurrentCommand[CommandLength] = '\0';
                    }
                } else if (strcmp(LastChar, "Enter") == 0) {
                    RunCommand(CurrentCommand, CommandLength);
                } else {
                    if (CommandLength < MAX_COMMAND_LENGTH - 1) {
                        CurrentCommand[CommandLength] = LastChar[0];
                        CommandLength++;
                        CurrentCommand[CommandLength] = '\0';
                    }
                }
            }
        }
    }
}

void _start(void) {
    kernel_main();
}

linker.ld :

ENTRY(_start)

SECTIONS
{
    . = 0x1000;

    .text : {
        *(.text)
    }

    .data : {
        *(.data)
    }

    .bss : {
        *(.bss COMMON)
    }
}

I use these commands for compilation:

nasm -f bin -o bootloader.bin bootloader.asm
i686-elf-gcc -ffreestanding -m32 -c kernel.c -o kernel.o
i686-elf-ld -T linker.ld -o kernel.bin -m elf_i386 kernel.o
dd if=bootloader.bin of=floppy.img bs=512 seek=0
dd if=kernel.bin of=floppy.img bs=512 seek=4
qemu-system-i386 -drive format=raw,file=floppy.img

I expect it to run without problems, but it gets stuck in a loop where a blinking Booting from Hard Drive... is displayed.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论