Begin NBOOT V2, Cleanup old files
This commit is contained in:
parent
843d3b6c0c
commit
e1696b82e7
25
build.i686
25
build.i686
@ -39,26 +39,28 @@ case $yn in
|
||||
echo ----------------
|
||||
|
||||
sudo losetup -d /dev/loop900
|
||||
dd if=/dev/zero of=build/main.img bs=512 count=50000
|
||||
dd if=/dev/zero of=build/main.img bs=512 count=2880
|
||||
mkdir -p build/mnt
|
||||
sudo losetup -P /dev/loop900 build/main.img
|
||||
sudo parted /dev/loop900 mktable msdos
|
||||
sudo parted /dev/loop900 mkpart primary fat16 2048s 100%
|
||||
sudo parted /dev/loop900p1 set 1 boot on
|
||||
sudo mkfs.fat -F16 /dev/loop900p1
|
||||
sudo mount /dev/loop900p1 build/mnt
|
||||
sudo mkfs.fat -F12 /dev/loop900
|
||||
sudo mount /dev/loop900 build/mnt
|
||||
sudo mkdir build/mnt/boot
|
||||
sudo mkdir build/mnt/boot/grub
|
||||
sudo mkdir build/mnt/misc
|
||||
sudo mkdir build/mnt/misc/src
|
||||
sudo cp -r src/* build/mnt/src
|
||||
sudo cp -r src/* build/mnt/misc/src
|
||||
sudo cp -r grub/* build/mnt/boot/grub
|
||||
sudo cp build/nanite.bin build/mnt/boot/nanite
|
||||
sudo grub-install \
|
||||
--install-modules="part_msdos gettext all_video gfxterm png normal echo multiboot2" \
|
||||
--install-modules="part_msdos normal echo multiboot2 ls" \
|
||||
--locales=en@quot \
|
||||
--fonts=none \
|
||||
--themes=none \
|
||||
--boot-directory=build/mnt/boot \
|
||||
--target=i386-pc \
|
||||
--bootloader-id=GRUB \
|
||||
--allow-floppy \
|
||||
--force \
|
||||
/dev/loop900 -v
|
||||
sudo umount build/mnt
|
||||
sudo losetup -d /dev/loop900
|
||||
@ -86,8 +88,11 @@ case $yn in
|
||||
-serial chardev:serial1 \
|
||||
-audiodev pa,id=speaker \
|
||||
-machine pcspk-audiodev=speaker \
|
||||
-hda build/main.img \
|
||||
-m size=16M
|
||||
-fda build/main.img \
|
||||
-m size=4M \
|
||||
-vga std \
|
||||
-cpu 486-v1 \
|
||||
-name Nanite
|
||||
echo --------
|
||||
echo Finshed!
|
||||
echo --------
|
||||
|
||||
13
doc/Bootloader.md
Normal file
13
doc/Bootloader.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Bootloader
|
||||
|
||||
Nanite has support for a couple of loaders, including GRUB2 and anything supporting the multiboot2 standard
|
||||
Nanite ALSO has its own custom bootloader called NBOOT, while temporarily abandoned between 2025-2026 its being re-written from scratch.
|
||||
|
||||
## GRUB
|
||||
|
||||
Grub's support is... mixed? its fairly buggy as it falls back on BIOS memory detection (since i can't seem to get multiboot2's mem info block to work...)
|
||||
Its very Useful for testing tho
|
||||
|
||||
## NBOOT
|
||||
|
||||
NBOOT is, experimental and unfinished, looking at it wrong would likely break it.
|
||||
@ -3,26 +3,15 @@ set default=0
|
||||
set pager=1
|
||||
|
||||
insmod part_msdos
|
||||
set root='hd0,1'
|
||||
set root='fd0'
|
||||
|
||||
set gfxmode=800x600
|
||||
insmod all_video
|
||||
set locale_dir=$prefix/locale
|
||||
set lang=en_CA
|
||||
insmod gettext
|
||||
|
||||
terminal_input console
|
||||
|
||||
insmod gfxmenu
|
||||
# loadfont /boot/grub/themes/nanite/font10.pf2
|
||||
# loadfont /boot/grub/themes/nanite/font12.pf2
|
||||
# loadfont /boot/grub/themes/nanite/font14.pf2
|
||||
# set theme=/boot/grub/themes/nanite/theme.txt
|
||||
# export theme
|
||||
insmod png
|
||||
|
||||
menuentry "NANITE" {
|
||||
set root='hd0,1'
|
||||
set root='fd0'
|
||||
insmod fat
|
||||
multiboot2 /boot/nanite
|
||||
echo "Booting NANITE..."
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,40 +0,0 @@
|
||||
# Nanite GRUB 2 Theme
|
||||
|
||||
message-font: "DEFCON Regular 14"
|
||||
message-color: "#FFF"
|
||||
terminal-font: "DEFCON Regular 12"
|
||||
desktop-image: "background.png"
|
||||
desktop-image-scale-method: "crop"
|
||||
|
||||
|
||||
#boot menu
|
||||
+ boot_menu {
|
||||
left = 10%
|
||||
width = 80%
|
||||
top = 20%
|
||||
height = 50%
|
||||
item_font = "DEFCON Regular 12"
|
||||
item_color = "#fff"
|
||||
selected_item_font = "DEFCON Regular 14"
|
||||
selected_item_color= "#f0f"
|
||||
icon_height = 25
|
||||
icon_width = 25
|
||||
item_height = 26
|
||||
item_padding = 0
|
||||
item_icon_space = 0
|
||||
item_spacing = 1
|
||||
scrollbar = true
|
||||
scrollbar_width = 20
|
||||
}
|
||||
|
||||
+ label {
|
||||
top = 100%-25
|
||||
left = 0
|
||||
width = 100%
|
||||
height = 20
|
||||
text = "@KEYMAP_MIDDLE@"
|
||||
align = "center"
|
||||
font = "DEFCON Regular 10"
|
||||
color = "#FFF"
|
||||
bg_color = "#000"
|
||||
}
|
||||
@ -20,18 +20,6 @@
|
||||
align 4
|
||||
%endmacro
|
||||
|
||||
section .boot
|
||||
extern start
|
||||
global _start
|
||||
_start:
|
||||
push 0
|
||||
popf
|
||||
push ebx
|
||||
push eax
|
||||
call start
|
||||
cli
|
||||
hlt
|
||||
|
||||
section .multiboot
|
||||
header_start:
|
||||
dd 0xe85250d6 ; magic number
|
||||
|
||||
@ -157,8 +157,8 @@ char kscan() {
|
||||
case KEYBOARD_LAYOUT_8: _keyboard_scancode = 0; return '8';
|
||||
case KEYBOARD_LAYOUT_9: _keyboard_scancode = 0; return '9';
|
||||
case KEYBOARD_LAYOUT_0: _keyboard_scancode = 0; return '0';
|
||||
case KEYBOARD_LAYOUT_OEM_MI: _keyboard_scancode = 0; return '-';
|
||||
case KEYBOARD_LAYOUT_OEM_PL: _keyboard_scancode = 0; return '=';
|
||||
case KEYBOARD_LAYOUT_OEM_MI: _keyboard_scancode = 0; if(_shift == true) return '_'; else return '-';
|
||||
case KEYBOARD_LAYOUT_OEM_PL: _keyboard_scancode = 0; if(_shift == true) return '+'; else return '=';
|
||||
case KEYBOARD_LAYOUT_BACK: _keyboard_scancode = 0; return '\b';
|
||||
case KEYBOARD_LAYOUT_TAB: _keyboard_scancode = 0; return '\t';
|
||||
case KEYBOARD_LAYOUT_Q: _keyboard_scancode = 0; return 'Q';
|
||||
@ -173,7 +173,7 @@ char kscan() {
|
||||
case KEYBOARD_LAYOUT_P: _keyboard_scancode = 0; return 'P';
|
||||
case KEYBOARD_LAYOUT_OEM_4: _keyboard_scancode = 0; return '[';
|
||||
case KEYBOARD_LAYOUT_OEM_6: _keyboard_scancode = 0; return ']';
|
||||
case KEYBOARD_LAYOUT_OEM_5: _keyboard_scancode = 0; return '\\';
|
||||
case KEYBOARD_LAYOUT_OEM_5: _keyboard_scancode = 0; if(_shift == true) return '|'; else return '\\';
|
||||
case KEYBOARD_LAYOUT_A: _keyboard_scancode = 0; return 'A';
|
||||
case KEYBOARD_LAYOUT_S: _keyboard_scancode = 0; return 'S';
|
||||
case KEYBOARD_LAYOUT_D: _keyboard_scancode = 0; return 'D';
|
||||
@ -183,7 +183,7 @@ char kscan() {
|
||||
case KEYBOARD_LAYOUT_J: _keyboard_scancode = 0; return 'J';
|
||||
case KEYBOARD_LAYOUT_K: _keyboard_scancode = 0; return 'K';
|
||||
case KEYBOARD_LAYOUT_L: _keyboard_scancode = 0; return 'L';
|
||||
case KEYBOARD_LAYOUT_OEM_1: _keyboard_scancode = 0; return ';';
|
||||
case KEYBOARD_LAYOUT_OEM_1: _keyboard_scancode = 0; if(_shift == true) return ':'; else return ';';
|
||||
case KEYBOARD_LAYOUT_OEM_7: _keyboard_scancode = 0; return '\'';
|
||||
case KEYBOARD_LAYOUT_RETURN: _keyboard_scancode = 0; return '\n';
|
||||
case KEYBOARD_LAYOUT_Z: _keyboard_scancode = 0; return 'Z';
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
ENTRY(_start)
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.multiboot : { __multiboot_start = .; *(.multiboot)}
|
||||
.notes : { __notes_start = .; *(.notes) }
|
||||
.boot : { __boot_start = .; *(.boot) }
|
||||
.entry : { __entry_start = .; *(.entry) }
|
||||
.entry : { __entry_start = .; *(.entry) }
|
||||
.text : { __text_start = .; *(.text) }
|
||||
.data : { __data_start = .; *(.data) }
|
||||
.rodata : { __rodata_start = .; *(.rodata*) }
|
||||
|
||||
@ -48,8 +48,6 @@
|
||||
|
||||
// Utilities
|
||||
|
||||
#include <util/param.h>
|
||||
#include <util/util.h>
|
||||
#include <util/binary.h>
|
||||
|
||||
// Other
|
||||
@ -67,7 +65,7 @@ extern int uptime; // System uptime measured by precision timer unit.
|
||||
uint16_t DEBUG_COM_PORT = COM1_PORT; // COM Port to Output Debug strings to
|
||||
|
||||
/*Main Kernel Function*/
|
||||
void start(unsigned long magic, unsigned long address) {
|
||||
void __attribute__((section(".entry"))) start(unsigned long magic, unsigned long address) {
|
||||
|
||||
struct multiboot_tag* tag;
|
||||
|
||||
@ -121,7 +119,6 @@ void start(unsigned long magic, unsigned long address) {
|
||||
// Hardware Detection
|
||||
Serial_Printf(DEBUG_COM_PORT, "MEMORY:> There is %dKB of Memory Available\nThe Kernel is loaded between 0x%x and 0x%x\n", Detect_Memory(), __bss_start, __end);
|
||||
printf("%dKB Of Memory Availible!\n", Detect_Memory());
|
||||
// printf("Random Number! %u\n", rand());
|
||||
|
||||
// Serial_Printf(DEBUG_COM_PORT, "CPU Vendor: %s\n", CPUID_Get_Vendor()); // CPUID Stuff is pain and suffering, like page faults and suffering
|
||||
|
||||
@ -144,16 +141,17 @@ void start(unsigned long magic, unsigned long address) {
|
||||
printf("Would you like to change the time and date? [y/N] ");
|
||||
scanf("%s", answer);
|
||||
if (!strcmp(answer, "Y") || !strcmp(answer, "y")) {
|
||||
printf("Please insert Date and Time in [SS]:[MM]:[HH] [DD]/[MM]/[YYYY] Format: ");
|
||||
printf("Please insert Date and Time in [SS]:[MM]:[HH] [DD]/[MM]/[YYYY] Format:\n");
|
||||
scanf("%s", answer);
|
||||
printf("\n");
|
||||
}
|
||||
printf("Starting Shell...");
|
||||
spinner(20);
|
||||
spinner(20); // yes. i fake the loading, i think its funny cope
|
||||
printf("Done!\n");
|
||||
for(;;) {
|
||||
char* input;
|
||||
printf(":>");
|
||||
scanf("");
|
||||
scanf("%s", input);
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@ -404,7 +404,9 @@ int scanf(const char* fmt, ...) {
|
||||
switch (character) {
|
||||
case '\n': printf("\n");
|
||||
return 0;
|
||||
case '\b': printf("\b ");
|
||||
case '\t': printf(" ");
|
||||
break;
|
||||
case '\b': printf("\b "); // keep here lmao.
|
||||
default: if(character != 0) {
|
||||
if(_shift == true) {
|
||||
printf("%c", character);
|
||||
@ -424,10 +426,9 @@ int scanf(const char* fmt, ...) {
|
||||
case '\n': printf("\n");
|
||||
*va_arg(args, char*) = *buffer;
|
||||
return 0;
|
||||
case '\b': printf("\b"); i--; buffer[i] = '\0';
|
||||
break;
|
||||
case '\t': printf(" ");
|
||||
break;
|
||||
case '\b': printf("\b "); buffer[i] = '\0'; i--;
|
||||
default: if(character != 0) {
|
||||
if(_shift == true) {
|
||||
printf("%c", character);
|
||||
|
||||
@ -10,11 +10,3 @@ uint8_t Get_Bit(uint8_t bits, uint8_t pos)
|
||||
{
|
||||
return (bits >> pos) & 0x01;
|
||||
}
|
||||
|
||||
// int Byte_Parse(int8_t byteFlag, int whichBit)
|
||||
// {
|
||||
// if (whichBit > 0 && whichBit <= 8)
|
||||
// return (byteFlag & (1<<(whichBit-1)));
|
||||
// else
|
||||
// return 0;
|
||||
// }
|
||||
@ -12,5 +12,3 @@
|
||||
#define BCD2BIN(bcd) ((((bcd)&15) + ((bcd)>>4)*10)) // Takes value in `bcd` and outputs it as binary
|
||||
|
||||
uint8_t Get_Bit(uint8_t bits, uint8_t pos);
|
||||
|
||||
//int Byte_Parse(int8_t byteFlag, int whichBit);
|
||||
@ -1,14 +0,0 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#include "param.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int paramloader(char filename) {
|
||||
printf("Sorry! This is not currently implemented, Need to Make disk calls and kinda uhm... forgot? i didn't before soooooo YEP!");
|
||||
printf("And heres yer filename: %s", filename);
|
||||
return 0;
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
int paramloader(char filename);
|
||||
@ -1,40 +0,0 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#include "util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int string_length(char s[]) {
|
||||
int i = 0;
|
||||
while (s[i] != '\0') {
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void append(char s[], char n) {
|
||||
int len = string_length(s);
|
||||
s[len] = n;
|
||||
s[len + 1] = '\0';
|
||||
}
|
||||
|
||||
// void Print_Storage_Types(int masterFDDType, int slaveFDDType)
|
||||
// {
|
||||
// // Master FDD
|
||||
// if (masterFDDType == 0) printf("No Master Floppy Drive Detected!\n");
|
||||
// if (masterFDDType == 1) printf("Master Floppy Drive Detected!\nType: 360 KB 5.25 Inch Drive\n");
|
||||
// if (masterFDDType == 2) printf("Master Floppy Drive Detected!\nType: 1.2 MB 5.25 Inch Drive\n");
|
||||
// if (masterFDDType == 3) printf("Master Floppy Drive Detected!\nType: 720 KB 3.5 Inch Drive\n");
|
||||
// if (masterFDDType == 4) printf("Master Floppy Drive Detected!\nType: 1.44 MB 3.5 Inch Drive\n");
|
||||
// if (masterFDDType == 5) printf("Master Floppy Drive Detected!\nType: 2.88 MB 3.5 Inch Drive\n");
|
||||
// // Slave FDD
|
||||
// if (slaveFDDType == 0) printf("No Slave Floppy Drive Detected!\n");
|
||||
// if (slaveFDDType == 1) printf("Slave Floppy Drive Detected!\nType: 360 KB 5.25 Inch Drive\n");
|
||||
// if (slaveFDDType == 2) printf("Slave Floppy Drive Detected!\nType: 1.2 MB 5.25 Inch Drive\n");
|
||||
// if (slaveFDDType == 3) printf("Slave Floppy Drive Detected!\nType: 720 KB 3.5 Inch Drive\n");
|
||||
// if (slaveFDDType == 4) printf("Slave Floppy Drive Detected!\nType: 1.44 MB 3.5 Inch Drive\n");
|
||||
// if (slaveFDDType == 5) printf("Slave Floppy Drive Detected!\nType: 2.88 MB 3.5 Inch Drive\n");
|
||||
// }
|
||||
@ -1,12 +0,0 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n)))
|
||||
|
||||
int string_length(char s[]);
|
||||
void append(char s[], char n);
|
||||
// void Print_Storage_Types(int masterFDDType, int slaveFDDType);
|
||||
@ -6,6 +6,6 @@
|
||||
#pragma once
|
||||
|
||||
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/" // Nanite's Logo as a formatted string
|
||||
#define VERSION "RD-00128" // Current Version of Nanite
|
||||
#define VERSION "RD-00132" // Current Version of Nanite
|
||||
#define BOOTLOGO " _ ______ ____ ____ ______\n / | / / __ )/ __ \\/ __ /_ __/\n / |/ / __ / / / / / / // / \n / /| / /_/ / /_/ / /_/ // / \n/_/ |_/_____/\\____/\\____//_/ \n" // Old bootloader logo
|
||||
// one day i will re-implement NBOOT V 2
|
||||
|
||||
14
src/nboot/bootsector/Makefile
Normal file
14
src/nboot/bootsector/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
BUILD_DIR?=build/
|
||||
TARGET_ASMFLAGS += -f bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: bootsector
|
||||
|
||||
bootsector: $(BUILD_DIR)/bootsector.bin
|
||||
|
||||
$(BUILD_DIR)/bootsector.bin:
|
||||
$(TARGET_ASM) bootsector.asm $(TARGET_ASMFLAGS) -o $(BUILD_DIR)/bootsector.bin
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/bootsector.bin
|
||||
396
src/nboot/bootsector/bootsector.asm
Normal file
396
src/nboot/bootsector/bootsector.asm
Normal file
@ -0,0 +1,396 @@
|
||||
;/////////////////////;
|
||||
;NBOOT ;
|
||||
;COPYRIGHT (C) 2026 ;
|
||||
;Xircon ;
|
||||
;/////////////////////;
|
||||
org 0x7C00
|
||||
[bits 16]
|
||||
|
||||
|
||||
%define ENDL 0x0D, 0x0A
|
||||
|
||||
|
||||
;
|
||||
; FAT12 header
|
||||
;
|
||||
jmp short start
|
||||
nop
|
||||
|
||||
bdb_oem: db 'MSWIN4.1' ; 8 bytes
|
||||
bdb_bytes_per_sector: dw 512
|
||||
bdb_sectors_per_cluster: db 1
|
||||
bdb_reserved_sectors: dw 1
|
||||
bdb_fat_count: db 2
|
||||
bdb_dir_entries_count: dw 0E0h
|
||||
bdb_total_sectors: dw 2880 ; 2880 * 512 = 1.44MB
|
||||
bdb_media_descriptor_type: db 0F0h ; F0 = 3.5" floppy disk
|
||||
bdb_sectors_per_fat: dw 9 ; 9 sectors/fat
|
||||
bdb_sectors_per_track: dw 18
|
||||
bdb_heads: dw 2
|
||||
bdb_hidden_sectors: dd 0
|
||||
bdb_large_sector_count: dd 0
|
||||
|
||||
; extended boot record
|
||||
ebr_drive_number: db 0 ; 0x00 floppy, 0x80 hdd, useless
|
||||
db 0 ; reserved
|
||||
ebr_signature: db 29h
|
||||
ebr_volume_id: db 12h, 34h, 56h, 78h ; serial number, value doesn't matter
|
||||
ebr_volume_label: db 'NANITE ' ; 11 bytes, padded with spaces
|
||||
ebr_system_id: db 'FAT12 ' ; 8 bytes
|
||||
|
||||
;
|
||||
; Code goes here
|
||||
;
|
||||
|
||||
start:
|
||||
; setup data segments
|
||||
mov ax, 0 ; can't set ds/es directly
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
; setup stack
|
||||
mov ss, ax
|
||||
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
|
||||
|
||||
; some BIOSes might start us at 07C0:0000 instead of 0000:7C00, make sure we are in the
|
||||
; expected location
|
||||
push es
|
||||
push word .after
|
||||
retf
|
||||
|
||||
.after:
|
||||
|
||||
; read something from floppy disk
|
||||
; BIOS should set DL to drive number
|
||||
mov [ebr_drive_number], dl
|
||||
|
||||
; show loading message
|
||||
mov si, msg_loading
|
||||
call puts
|
||||
|
||||
; read drive parameters (sectors per track and head count),
|
||||
; instead of relying on data on formatted disk
|
||||
push es
|
||||
mov ah, 08h
|
||||
int 13h
|
||||
jc error
|
||||
pop es
|
||||
|
||||
and cl, 0x3F ; remove top 2 bits
|
||||
xor ch, ch
|
||||
mov [bdb_sectors_per_track], cx ; sector count
|
||||
|
||||
inc dh
|
||||
mov [bdb_heads], dh ; head count
|
||||
|
||||
; compute LBA of root directory = reserved + fats * sectors_per_fat
|
||||
; note: this section can be hardcoded
|
||||
mov ax, [bdb_sectors_per_fat]
|
||||
mov bl, [bdb_fat_count]
|
||||
xor bh, bh
|
||||
mul bx ; ax = (fats * sectors_per_fat)
|
||||
add ax, [bdb_reserved_sectors] ; ax = LBA of root directory
|
||||
push ax
|
||||
|
||||
; compute size of root directory = (32 * number_of_entries) / bytes_per_sector
|
||||
mov ax, [bdb_dir_entries_count]
|
||||
shl ax, 5 ; ax *= 32
|
||||
xor dx, dx ; dx = 0
|
||||
div word [bdb_bytes_per_sector] ; number of sectors we need to read
|
||||
|
||||
test dx, dx ; if dx != 0, add 1
|
||||
jz .root_dir_after
|
||||
inc ax ; division remainder != 0, add 1
|
||||
; this means we have a sector only partially filled with entries
|
||||
.root_dir_after:
|
||||
|
||||
; read root directory
|
||||
mov cl, al ; cl = number of sectors to read = size of root directory
|
||||
pop ax ; ax = LBA of root directory
|
||||
mov dl, [ebr_drive_number] ; dl = drive number (we saved it previously)
|
||||
mov bx, buffer ; es:bx = buffer
|
||||
call disk_read
|
||||
|
||||
; search for stage2
|
||||
xor bx, bx
|
||||
mov di, buffer
|
||||
|
||||
; .search_boot_dir:
|
||||
; mov si, boot_dir
|
||||
; mov cx, 11 ; compare up to 11 characters
|
||||
; push di
|
||||
; repe cmpsb
|
||||
; pop di
|
||||
; je .found_boot_dir
|
||||
|
||||
; add di, 32
|
||||
; inc bx
|
||||
; cmp bx, [bdb_dir_entries_count]
|
||||
; jl .search_boot_dir
|
||||
|
||||
; ; kernel not found
|
||||
; jmp error
|
||||
|
||||
; .found_boot_dir:
|
||||
; hlt
|
||||
|
||||
.search_stage2:
|
||||
mov si, file_stage2_bin
|
||||
mov cx, 11 ; compare up to 11 characters
|
||||
push di
|
||||
repe cmpsb
|
||||
pop di
|
||||
je .found_stage2
|
||||
|
||||
add di, 32
|
||||
inc bx
|
||||
cmp bx, [bdb_dir_entries_count]
|
||||
jl .search_stage2
|
||||
|
||||
; kernel not found
|
||||
jmp error
|
||||
|
||||
.found_stage2:
|
||||
|
||||
; di should have the address to the entry
|
||||
mov ax, [di + 26] ; first logical cluster field (offset 26)
|
||||
mov [stage2_cluster], ax
|
||||
|
||||
; load FAT from disk into memory
|
||||
mov ax, [bdb_reserved_sectors]
|
||||
mov bx, buffer
|
||||
mov cl, [bdb_sectors_per_fat]
|
||||
mov dl, [ebr_drive_number]
|
||||
call disk_read
|
||||
|
||||
; read kernel and process FAT chain
|
||||
mov bx, STAGE2_LOAD_SEGMENT
|
||||
mov es, bx
|
||||
mov bx, STAGE2_LOAD_OFFSET
|
||||
|
||||
.load_stage2_loop:
|
||||
|
||||
; Read next cluster
|
||||
mov ax, [stage2_cluster]
|
||||
|
||||
; not nice :( hardcoded value
|
||||
add ax, 31 ; first cluster = (kernel_cluster - 2) * sectors_per_cluster + start_sector
|
||||
; start sector = reserved + fats + root directory size = 1 + 18 + 134 = 33
|
||||
mov cl, 1
|
||||
mov dl, [ebr_drive_number]
|
||||
call disk_read
|
||||
|
||||
add bx, [bdb_bytes_per_sector]
|
||||
|
||||
; compute location of next cluster
|
||||
mov ax, [stage2_cluster]
|
||||
mov cx, 3
|
||||
mul cx
|
||||
mov cx, 2
|
||||
div cx ; ax = index of entry in FAT, dx = cluster mod 2
|
||||
|
||||
mov si, buffer
|
||||
add si, ax
|
||||
mov ax, [ds:si] ; read entry from FAT table at index ax
|
||||
|
||||
or dx, dx
|
||||
jz .even
|
||||
|
||||
.odd:
|
||||
shr ax, 4
|
||||
jmp .next_cluster_after
|
||||
|
||||
.even:
|
||||
and ax, 0x0FFF
|
||||
|
||||
.next_cluster_after:
|
||||
cmp ax, 0x0FF8 ; end of chain
|
||||
jae .read_finish
|
||||
|
||||
mov [stage2_cluster], ax
|
||||
jmp .load_stage2_loop
|
||||
|
||||
.read_finish:
|
||||
|
||||
; jump to our kernel
|
||||
mov dl, [ebr_drive_number] ; boot device in dl
|
||||
|
||||
mov ax, STAGE2_LOAD_SEGMENT ; set segment registers
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
jmp STAGE2_LOAD_SEGMENT:STAGE2_LOAD_OFFSET
|
||||
|
||||
jmp wait_key_and_reboot ; should never happen
|
||||
|
||||
cli ; disable interrupts, this way CPU can't get out of "halt" state
|
||||
hlt
|
||||
|
||||
|
||||
;
|
||||
; Error handler (i needed more room.)
|
||||
;
|
||||
|
||||
error:
|
||||
mov si, msg_error
|
||||
call puts
|
||||
jmp wait_key_and_reboot
|
||||
|
||||
wait_key_and_reboot:
|
||||
mov ah, 0
|
||||
int 16h ; wait for keypress
|
||||
jmp 0FFFFh:0 ; jump to beginning of BIOS, should reboot
|
||||
|
||||
.halt:
|
||||
cli ; disable interrupts, this way CPU can't get out of "halt" state
|
||||
hlt
|
||||
|
||||
|
||||
;
|
||||
; Prints a string to the screen
|
||||
; Params:
|
||||
; - ds:si points to string
|
||||
;
|
||||
puts:
|
||||
; save registers we will modify
|
||||
push si
|
||||
push ax
|
||||
push bx
|
||||
|
||||
.loop:
|
||||
lodsb ; loads next character in al
|
||||
or al, al ; verify if next character is null?
|
||||
jz .done
|
||||
|
||||
mov ah, 0x0E ; call bios interrupt
|
||||
mov bh, 0 ; set page number to 0
|
||||
int 0x10
|
||||
|
||||
jmp .loop
|
||||
|
||||
.done:
|
||||
pop bx
|
||||
pop ax
|
||||
pop si
|
||||
ret
|
||||
|
||||
;
|
||||
; Disk routines
|
||||
;
|
||||
|
||||
;
|
||||
; Converts an LBA address to a CHS address
|
||||
; Parameters:
|
||||
; - ax: LBA address
|
||||
; Returns:
|
||||
; - cx [bits 0-5]: sector number
|
||||
; - cx [bits 6-15]: cylinder
|
||||
; - dh: head
|
||||
;
|
||||
|
||||
lba_to_chs:
|
||||
|
||||
push ax
|
||||
push dx
|
||||
|
||||
xor dx, dx ; dx = 0
|
||||
div word [bdb_sectors_per_track] ; ax = LBA / SectorsPerTrack
|
||||
; dx = LBA % SectorsPerTrack
|
||||
|
||||
inc dx ; dx = (LBA % SectorsPerTrack + 1) = sector
|
||||
mov cx, dx ; cx = sector
|
||||
|
||||
xor dx, dx ; dx = 0
|
||||
div word [bdb_heads] ; ax = (LBA / SectorsPerTrack) / Heads = cylinder
|
||||
; dx = (LBA / SectorsPerTrack) % Heads = head
|
||||
mov dh, dl ; dh = head
|
||||
mov ch, al ; ch = cylinder (lower 8 bits)
|
||||
shl ah, 6
|
||||
or cl, ah ; put upper 2 bits of cylinder in CL
|
||||
|
||||
pop ax
|
||||
mov dl, al ; restore DL
|
||||
pop ax
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
; Reads sectors from a disk
|
||||
; Parameters:
|
||||
; - ax: LBA address
|
||||
; - cl: number of sectors to read (up to 128)
|
||||
; - dl: drive number
|
||||
; - es:bx: memory address where to store read data
|
||||
;
|
||||
disk_read:
|
||||
|
||||
push ax ; save registers we will modify
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
|
||||
push cx ; temporarily save CL (number of sectors to read)
|
||||
call lba_to_chs ; compute CHS
|
||||
pop ax ; AL = number of sectors to read
|
||||
|
||||
mov ah, 02h
|
||||
mov di, 3 ; retry count
|
||||
|
||||
.retry:
|
||||
pusha ; save all registers, we don't know what bios modifies
|
||||
stc ; set carry flag, some BIOS'es don't set it
|
||||
int 13h ; carry flag cleared = success
|
||||
jnc .done ; jump if carry not set
|
||||
|
||||
; read failed
|
||||
popa
|
||||
call disk_reset
|
||||
|
||||
dec di
|
||||
test di, di
|
||||
jnz .retry
|
||||
|
||||
.fail:
|
||||
; all attempts are exhausted
|
||||
jmp error
|
||||
|
||||
.done:
|
||||
popa
|
||||
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax ; restore registers modified
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
; Resets disk controller
|
||||
; Parameters:
|
||||
; dl: drive number
|
||||
;
|
||||
disk_reset:
|
||||
pusha
|
||||
mov ah, 0
|
||||
stc
|
||||
int 13h
|
||||
jc error
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
msg_loading: db 'Loading NBOOT...', ENDL, 0
|
||||
msg_error: db 'ERR!', ENDL, 0
|
||||
file_stage2_bin: db 'NBOOT BIN'
|
||||
boot_dir: db 'BOOT '
|
||||
stage2_cluster: dw 0
|
||||
|
||||
STAGE2_LOAD_SEGMENT equ 0x0
|
||||
STAGE2_LOAD_OFFSET equ 0x500
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
buffer:
|
||||
44
src/nboot/stage2/Makefile
Normal file
44
src/nboot/stage2/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
TARGET_ASMFLAGS += -f elf
|
||||
TARGET_CFLAGS += -ffreestanding -nostdlib -I.
|
||||
TARGET_LIBS += -lgcc
|
||||
TARGET_LINKFLAGS += -T linker.ld -nostdlib
|
||||
|
||||
HEADERS_C = $(wildcard *.h) \
|
||||
$(wildcard */*.h) \
|
||||
$(wildcard */*/*.h) \
|
||||
$(wildcard */*/*/*.h) \
|
||||
|
||||
SOURCES_C = $(wildcard *.c) \
|
||||
$(wildcard */*.c) \
|
||||
$(wildcard */*/*.c) \
|
||||
$(wildcard */*/*/*.c) \
|
||||
|
||||
OBJECTS_C = $(patsubst %.c, $(BUILD_DIR)/nboot/c/%.obj, $(SOURCES_C))
|
||||
|
||||
HEADERS_ASM = $(wildcard *.inc)
|
||||
SOURCES_ASM = $(wildcard *.asm)
|
||||
|
||||
OBJECTS_ASM = $(patsubst %.asm, $(BUILD_DIR)/nboot/asm/%.obj, $(SOURCES_ASM))
|
||||
|
||||
.PHONY: all nboot clean always
|
||||
|
||||
all: nboot
|
||||
|
||||
nboot: $(BUILD_DIR)/nboot.bin
|
||||
|
||||
$(BUILD_DIR)/nboot.bin: $(OBJECTS_ASM) $(OBJECTS_C)
|
||||
@$(TARGET_LD) $(TARGET_LINKFLAGS) -Wl,-Map=$(BUILD_DIR)/kernel.map -o $@ $^ $(TARGET_LIBS)
|
||||
@echo "--> Created: nboot.bin"
|
||||
|
||||
$(BUILD_DIR)/nboot/c/%.obj: %.c $(HEADERS_C)
|
||||
@mkdir -p $(@D)
|
||||
@$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
|
||||
@echo "--> Compiled: " $<
|
||||
|
||||
$(BUILD_DIR)/nboot/asm/%.obj: %.asm $(HEADERS_ASM)
|
||||
@mkdir -p $(@D)
|
||||
@$(TARGET_ASM) $(TARGET_ASMFLAGS) -o $@ $<
|
||||
@echo "--> Compiled: " $<
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/nboot.bin
|
||||
175
src/nboot/stage2/entry.asm
Normal file
175
src/nboot/stage2/entry.asm
Normal file
@ -0,0 +1,175 @@
|
||||
;/////////////////////;
|
||||
;NBOOT ;
|
||||
;COPYRIGHT (C) 2026 ;
|
||||
;Xircon ;
|
||||
;/////////////////////;
|
||||
[bits 16]
|
||||
|
||||
section .entry
|
||||
|
||||
extern __bss_start
|
||||
extern __end
|
||||
|
||||
extern start
|
||||
global entry
|
||||
|
||||
entry:
|
||||
cli
|
||||
|
||||
; save boot drive
|
||||
mov [g_BootDrive], dl
|
||||
|
||||
; setup stack
|
||||
mov ax, ds
|
||||
mov ss, ax
|
||||
mov sp, 0xFFF0
|
||||
mov bp, sp
|
||||
|
||||
; switch to PMODE
|
||||
call EnableA20
|
||||
call LoadGDT
|
||||
|
||||
; set PMODE enable flag in CR0
|
||||
mov eax, CR0
|
||||
or al, 1
|
||||
mov cr0, eax
|
||||
|
||||
; far jmp into PMODE
|
||||
jmp dword 08h:.pmode
|
||||
|
||||
.pmode:
|
||||
; we are now in protected mode!
|
||||
[bits 32]
|
||||
|
||||
; 6 - setup segment registers
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov al, 0
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
; clear BSS (uninit data)
|
||||
mov edi, __bss_start
|
||||
mov ecx, __end
|
||||
sub ecx, edi
|
||||
|
||||
|
||||
xor edx, edx
|
||||
mov dl, [g_BootDrive]
|
||||
push edx
|
||||
call start
|
||||
|
||||
cli
|
||||
hlt
|
||||
|
||||
|
||||
|
||||
EnableA20:
|
||||
[bits 16]
|
||||
; disable keyboard
|
||||
call A20WaitInput
|
||||
mov al, KbdControllerDisableKeyboard
|
||||
out KbdControllerCommandPort, al
|
||||
|
||||
; read control output port
|
||||
call A20WaitInput
|
||||
mov al, KbdControllerReadCtrlOutputPort
|
||||
out KbdControllerCommandPort, al
|
||||
|
||||
call A20WaitOutput
|
||||
in al, KbdControllerDataPort
|
||||
push eax
|
||||
|
||||
; write control output port
|
||||
call A20WaitInput
|
||||
mov al, KbdControllerWriteCtrlOutputPort
|
||||
out KbdControllerCommandPort, al
|
||||
|
||||
call A20WaitInput
|
||||
pop eax
|
||||
or al, 2 ; bit 2 = A20 bit
|
||||
out KbdControllerDataPort, al
|
||||
|
||||
; enable keyboard
|
||||
call A20WaitInput
|
||||
mov al, KbdControllerEnableKeyboard
|
||||
out KbdControllerCommandPort, al
|
||||
|
||||
call A20WaitInput
|
||||
ret
|
||||
|
||||
|
||||
A20WaitInput:
|
||||
[bits 16]
|
||||
; wait until status bit 2 (input buffer) is 0
|
||||
; by reading from command port, we read status byte
|
||||
in al, KbdControllerCommandPort
|
||||
test al, 2
|
||||
jnz A20WaitInput
|
||||
ret
|
||||
|
||||
A20WaitOutput:
|
||||
[bits 16]
|
||||
; wait until status bit 1 (output buffer) is 1 so it can be read
|
||||
in al, KbdControllerCommandPort
|
||||
test al, 1
|
||||
jz A20WaitOutput
|
||||
ret
|
||||
|
||||
|
||||
LoadGDT:
|
||||
[bits 16]
|
||||
lgdt [g_GDTDesc]
|
||||
ret
|
||||
|
||||
|
||||
|
||||
KbdControllerDataPort equ 0x60
|
||||
KbdControllerCommandPort equ 0x64
|
||||
KbdControllerDisableKeyboard equ 0xAD
|
||||
KbdControllerEnableKeyboard equ 0xAE
|
||||
KbdControllerReadCtrlOutputPort equ 0xD0
|
||||
KbdControllerWriteCtrlOutputPort equ 0xD1
|
||||
|
||||
ScreenBuffer equ 0xB8000
|
||||
|
||||
g_GDT: ; NULL descriptor
|
||||
dq 0
|
||||
|
||||
; 32-bit code segment
|
||||
dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF for full 32-bit range
|
||||
dw 0 ; base (bits 0-15) = 0x0
|
||||
db 0 ; base (bits 16-23)
|
||||
db 10011010b ; access (present, ring 0, code segment, executable, direction 0, readable)
|
||||
db 11001111b ; granularity (4k pages, 32-bit pmode) + limit (bits 16-19)
|
||||
db 0 ; base high
|
||||
|
||||
; 32-bit data segment
|
||||
dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF for full 32-bit range
|
||||
dw 0 ; base (bits 0-15) = 0x0
|
||||
db 0 ; base (bits 16-23)
|
||||
db 10010010b ; access (present, ring 0, data segment, executable, direction 0, writable)
|
||||
db 11001111b ; granularity (4k pages, 32-bit pmode) + limit (bits 16-19)
|
||||
db 0 ; base high
|
||||
|
||||
; 16-bit code segment
|
||||
dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF
|
||||
dw 0 ; base (bits 0-15) = 0x0
|
||||
db 0 ; base (bits 16-23)
|
||||
db 10011010b ; access (present, ring 0, code segment, executable, direction 0, readable)
|
||||
db 00001111b ; granularity (1b pages, 16-bit pmode) + limit (bits 16-19)
|
||||
db 0 ; base high
|
||||
|
||||
; 16-bit data segment
|
||||
dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF
|
||||
dw 0 ; base (bits 0-15) = 0x0
|
||||
db 0 ; base (bits 16-23)
|
||||
db 10010010b ; access (present, ring 0, data segment, executable, direction 0, writable)
|
||||
db 00001111b ; granularity (1b pages, 16-bit pmode) + limit (bits 16-19)
|
||||
db 0 ; base high
|
||||
|
||||
g_GDTDesc: dw g_GDTDesc - g_GDT - 1 ; limit = size of GDT
|
||||
dd g_GDT ; address of GDT
|
||||
|
||||
g_BootDrive: db 0
|
||||
12
src/nboot/stage2/linker.ld
Normal file
12
src/nboot/stage2/linker.ld
Normal file
@ -0,0 +1,12 @@
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.entry : { __entry_start = .; *(.entry) }
|
||||
.text : { __text_start = .; *(.text) }
|
||||
.data : { __data_start = .; *(.data) }
|
||||
.rodata : { __rodata_start = .; *(.rodata*) }
|
||||
.bss : { __bss_start = .; *(.bss) }
|
||||
|
||||
__end = .;
|
||||
}
|
||||
10
src/nboot/stage2/main.c
Normal file
10
src/nboot/stage2/main.c
Normal file
@ -0,0 +1,10 @@
|
||||
/*----------------*\
|
||||
|NBOOT |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#include <version.h>
|
||||
|
||||
void __attribute__((section(".entry"))) start() {
|
||||
|
||||
}
|
||||
10
src/nboot/stage2/version.h
Normal file
10
src/nboot/stage2/version.h
Normal file
@ -0,0 +1,10 @@
|
||||
/*----------------*\
|
||||
|NBOOT |
|
||||
|Copyright (C) 2026|
|
||||
|Xircon |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
#define VERSION "RD-00002" // Current Version of Nanite
|
||||
#define LOGO " _ ______ ____ ____ ______\n / | / / __ )/ __ \\/ __ /_ __/\n / |/ / __ / / / / / / // / \n / /| / /_/ / /_/ / /_/ // / \n/_/ |_/_____/\\____/\\____//_/ \n"
|
||||
// one day i will re-implement NBOOT V 2
|
||||
Loading…
x
Reference in New Issue
Block a user