Initital Commit
This commit is contained in:
parent
cb8480c234
commit
803c228073
74
Makefile
Normal file
74
Makefile
Normal file
@ -0,0 +1,74 @@
|
||||
ASM=nasm
|
||||
CC=gcc
|
||||
CC16=/usr/bin/watcom/binl/wcc
|
||||
LD16=/usr/bin/watcom/binl/wlink
|
||||
|
||||
SRC_DIR=src
|
||||
TOOLS_DIR=tools
|
||||
BUILD_DIR=build
|
||||
|
||||
.PHONY: all floppy_image kernel bootloader clean always tools_fat
|
||||
|
||||
all: floppy_image tools_fat
|
||||
|
||||
#
|
||||
# Floppy image
|
||||
#
|
||||
floppy_image: $(BUILD_DIR)/main_floppy.img
|
||||
|
||||
$(BUILD_DIR)/main_floppy.img: bootloader kernel
|
||||
dd if=/dev/zero of=$(BUILD_DIR)/main_floppy.img bs=512 count=2880
|
||||
mkfs.fat -F 12 -n "Nanite" $(BUILD_DIR)/main_floppy.img
|
||||
dd if=$(BUILD_DIR)/stage1.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc
|
||||
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin"
|
||||
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin"
|
||||
mcopy -i $(BUILD_DIR)/main_floppy.img readme.txt "::readme.txt"
|
||||
|
||||
#
|
||||
# Bootloader
|
||||
#
|
||||
#
|
||||
bootloader: stage1 stage2
|
||||
|
||||
stage1: $(BUILD_DIR)/stage1.bin
|
||||
|
||||
$(BUILD_DIR)/stage1.bin: always
|
||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR))
|
||||
|
||||
stage2: $(BUILD_DIR)/stage2.bin
|
||||
|
||||
$(BUILD_DIR)/stage2.bin: always
|
||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR))
|
||||
|
||||
|
||||
#
|
||||
# Kernel
|
||||
#
|
||||
kernel: $(BUILD_DIR)/kernel.bin
|
||||
|
||||
$(BUILD_DIR)/kernel.bin: always
|
||||
$(MAKE) -C $(SRC_DIR)/kernel BUILD_DIR=$(abspath $(BUILD_DIR))
|
||||
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
tools_fat: $(BUILD_DIR)/tools/fat
|
||||
$(BUILD_DIR)/tools/fat: always $(TOOLS_DIR)/fat/fat.c
|
||||
mkdir -p $(BUILD_DIR)/tools
|
||||
$(CC) -g -o $(BUILD_DIR)/tools/fat $(TOOLS_DIR)/fat/fat.c
|
||||
|
||||
#
|
||||
# Always
|
||||
#
|
||||
always:
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
#
|
||||
# Clean
|
||||
#
|
||||
clean:
|
||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||
$(MAKE) -C $(SRC_DIR)/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||
rm -rf $(BUILD_DIR)/*
|
||||
rm -rf $(SRC_DIR)/bootloader/stage2/*.err
|
||||
7
bochs_config
Normal file
7
bochs_config
Normal file
@ -0,0 +1,7 @@
|
||||
megs: 128
|
||||
romimage: file=/usr/share/bochs/BIOS-bochs-legacy, address=0xffff0000
|
||||
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
|
||||
floppya: 1_44=build/main_floppy.img, status=inserted
|
||||
boot: floppy
|
||||
mouse: enabled=0
|
||||
display_library: x, options="gui_debug"
|
||||
52
build.sh
Normal file
52
build.sh
Normal file
@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
echo --------
|
||||
echo STARTING
|
||||
echo --------
|
||||
read -p "Do you want to clean old build files? (y/n) " yn
|
||||
|
||||
case $yn in
|
||||
y )
|
||||
|
||||
echo ---------------------------;
|
||||
echo Removing Old Build Files...;
|
||||
echo ---------------------------;
|
||||
|
||||
sudo make clean;
|
||||
echo -----;
|
||||
echo Done!;
|
||||
echo -----;
|
||||
;;
|
||||
n )
|
||||
echo ---------;
|
||||
echo Proceding;
|
||||
echo ---------;
|
||||
;;
|
||||
esac
|
||||
echo ------------
|
||||
echo COMPILING OS
|
||||
echo ------------
|
||||
|
||||
sudo make -s
|
||||
|
||||
echo ---------
|
||||
echo Finished!
|
||||
echo ---------
|
||||
read -p "Do you want to Start QEMU? (y/n) " yn
|
||||
|
||||
case $yn in
|
||||
y )
|
||||
echo -------------
|
||||
echo STARTING QEMU
|
||||
echo -------------
|
||||
sudo qemu-system-i386 -fda build/main_floppy.img
|
||||
echo --------
|
||||
echo Finshed!
|
||||
echo --------
|
||||
|
||||
;;
|
||||
n ) echo exiting...;
|
||||
exit;;
|
||||
* ) echo invalid response;
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
BIN
build/stage1.bin
Normal file
BIN
build/stage1.bin
Normal file
Binary file not shown.
BIN
build/stage2/asm/main.obj
Normal file
BIN
build/stage2/asm/main.obj
Normal file
Binary file not shown.
BIN
build/stage2/asm/x86.obj
Normal file
BIN
build/stage2/asm/x86.obj
Normal file
Binary file not shown.
BIN
build/stage2/c/main.obj
Normal file
BIN
build/stage2/c/main.obj
Normal file
Binary file not shown.
26
bx_enh_dbg.ini
Normal file
26
bx_enh_dbg.ini
Normal file
@ -0,0 +1,26 @@
|
||||
# bx_enh_dbg_ini
|
||||
SeeReg[0] = TRUE
|
||||
SeeReg[1] = TRUE
|
||||
SeeReg[2] = TRUE
|
||||
SeeReg[3] = TRUE
|
||||
SeeReg[4] = FALSE
|
||||
SeeReg[5] = FALSE
|
||||
SeeReg[6] = FALSE
|
||||
SeeReg[7] = FALSE
|
||||
SingleCPU = FALSE
|
||||
ShowIOWindows = TRUE
|
||||
ShowButtons = TRUE
|
||||
SeeRegColors = TRUE
|
||||
ignoreNxtT = TRUE
|
||||
ignSSDisasm = TRUE
|
||||
UprCase = 0
|
||||
DumpInAsciiMode = 3
|
||||
isLittleEndian = TRUE
|
||||
DefaultAsmLines = 512
|
||||
DumpWSIndex = 0
|
||||
DockOrder = 0x123
|
||||
ListWidthPix[0] = 179
|
||||
ListWidthPix[1] = 248
|
||||
ListWidthPix[2] = 283
|
||||
MainWindow = 0, 0, 714, 500
|
||||
FontName = Normal
|
||||
27
debug.sh
Normal file
27
debug.sh
Normal file
@ -0,0 +1,27 @@
|
||||
echo ------------
|
||||
echo COMPILING OS
|
||||
echo ------------
|
||||
|
||||
sudo make
|
||||
|
||||
echo ---------
|
||||
echo Finished!
|
||||
echo ---------
|
||||
read -p "Do you want to Start Bochs? (Y/n) " yn
|
||||
|
||||
case $yn in
|
||||
y )
|
||||
echo -------------
|
||||
echo STARTING Bochs
|
||||
echo -------------
|
||||
sudo bochs -f bochs_config
|
||||
echo --------
|
||||
echo Finshed!
|
||||
echo --------
|
||||
|
||||
;;
|
||||
n ) echo exiting...;
|
||||
exit;;
|
||||
* ) echo invalid response;
|
||||
exit 1;;
|
||||
esac
|
||||
5
readme.txt
Normal file
5
readme.txt
Normal file
@ -0,0 +1,5 @@
|
||||
###LAMBDA OS README
|
||||
|
||||
Test README
|
||||
|
||||
OMG i love CHEESE
|
||||
14
src/bootloader/stage1/Makefile
Normal file
14
src/bootloader/stage1/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
BUILD_DIR?=build/
|
||||
ASM?=nasm
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: stage1
|
||||
|
||||
stage1: $(BUILD_DIR)/stage1.bin
|
||||
|
||||
$(BUILD_DIR)/stage1.bin:
|
||||
$(ASM) boot.asm -f bin -o $(BUILD_DIR)/stage1.bin
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/stage1.bin
|
||||
383
src/bootloader/stage1/boot.asm
Normal file
383
src/bootloader/stage1/boot.asm
Normal file
@ -0,0 +1,383 @@
|
||||
;/////////////////////;
|
||||
;Nanite OS ;
|
||||
;COPYRIGHT (C) 2024 ;
|
||||
;Tyler McGurrin ;
|
||||
;/////////////////////;
|
||||
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 floppy_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 kernel.bin
|
||||
xor bx, bx
|
||||
mov di, buffer
|
||||
|
||||
.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 stage2_not_found_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 handlers
|
||||
;
|
||||
|
||||
floppy_error:
|
||||
mov si, msg_read_failed
|
||||
call puts
|
||||
jmp wait_key_and_reboot
|
||||
|
||||
stage2_not_found_error:
|
||||
mov si, msg_no_stage2
|
||||
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 floppy_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 floppy_error
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
msg_loading: db 'Starting Nanite 0.0.1a...', ENDL, 0
|
||||
msg_read_failed: db 'Cant Read Disk!', ENDL, 0
|
||||
msg_no_stage2: db 'Cant Find Stage 2!', ENDL, 0
|
||||
file_stage2_bin: db 'STAGE2 BIN'
|
||||
stage2_cluster: dw 0
|
||||
|
||||
STAGE2_LOAD_SEGMENT equ 0x2000
|
||||
STAGE2_LOAD_OFFSET equ 0
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
buffer:
|
||||
|
||||
33
src/bootloader/stage2/Makefile
Normal file
33
src/bootloader/stage2/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
BUILD_DIR?=build/
|
||||
ASM?=nasm
|
||||
ASMFLAGS?=-f obj
|
||||
CC16?=/usr/bin/watcom/binl/wcc
|
||||
CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq # -oneatxzh
|
||||
LD16?=/usr/bin/watcom/binl/wlink
|
||||
|
||||
SOURCES_C=$(wildcard *.c)
|
||||
SOURCES_ASM=$(wildcard *.asm)
|
||||
OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/stage2/c/%.obj, $(SOURCES_C))
|
||||
OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/stage2/asm/%.obj, $(SOURCES_ASM))
|
||||
|
||||
.PHONY: all stage2 clean always
|
||||
|
||||
all: stage2
|
||||
|
||||
stage2: $(BUILD_DIR)/stage2.bin
|
||||
|
||||
$(BUILD_DIR)/stage2.bin: $(OBJECTS_ASM) $(OBJECTS_C)
|
||||
$(LD16) NAME $(BUILD_DIR)/stage2.bin FILE \{ $(OBJECTS_ASM) $(OBJECTS_C) \} OPTION MAP=$(BUILD_DIR)/stage2.map @linker.lnk
|
||||
|
||||
$(BUILD_DIR)/stage2/c/%.obj: %.c always
|
||||
$(CC16) $(CFLAGS16) -fo=$@ $<
|
||||
|
||||
$(BUILD_DIR)/stage2/asm/%.obj: %.asm always
|
||||
$(ASM) $(ASMFLAGS) -o $@ $<
|
||||
|
||||
always:
|
||||
mkdir -p $(BUILD_DIR)/stage2/c
|
||||
mkdir -p $(BUILD_DIR)/stage2/asm
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/stage2.bin
|
||||
19
src/bootloader/stage2/disk.h
Normal file
19
src/bootloader/stage2/disk.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t id;
|
||||
uint16_t cylinders;
|
||||
uint16_t sectors;
|
||||
uint16_t heads;
|
||||
};
|
||||
|
||||
bool DISK_Initialize(DISK* disk, uint8_t driveNumber);
|
||||
bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t far* dataOut);
|
||||
|
||||
12
src/bootloader/stage2/linker.lnk
Normal file
12
src/bootloader/stage2/linker.lnk
Normal file
@ -0,0 +1,12 @@
|
||||
FORMAT RAW BIN
|
||||
OPTION QUIET,
|
||||
NODEFAULTLIBS,
|
||||
START=entry,
|
||||
VERBOSE,
|
||||
OFFSET=0,
|
||||
STACK=0x200
|
||||
ORDER
|
||||
CLNAME CODE
|
||||
SEGMENT _ENTRY
|
||||
SEGMENT _TEXT
|
||||
CLNAME DATA
|
||||
28
src/bootloader/stage2/main.asm
Normal file
28
src/bootloader/stage2/main.asm
Normal file
@ -0,0 +1,28 @@
|
||||
;/////////////////////;
|
||||
;Nanite OS ;
|
||||
;COPYRIGHT (C) 2024 ;
|
||||
;Tyler McGurrin ;
|
||||
;/////////////////////;
|
||||
bits 16
|
||||
|
||||
section _ENTRY class=CODE
|
||||
|
||||
extern _cstart_
|
||||
global entry
|
||||
|
||||
entry:
|
||||
cli
|
||||
; setup stack
|
||||
mov ax, ds
|
||||
mov ss, ax
|
||||
mov sp, 0
|
||||
mov bp, sp
|
||||
sti
|
||||
|
||||
; expect boot drive in dl, send it as argument to cstart function
|
||||
xor dh, dh
|
||||
push dx
|
||||
call _cstart_
|
||||
|
||||
cli
|
||||
hlt
|
||||
13
src/bootloader/stage2/main.c
Normal file
13
src/bootloader/stage2/main.c
Normal file
@ -0,0 +1,13 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
|
||||
void _cdecl cstart_(uint16_t bootDrive)
|
||||
{
|
||||
puts("Going from x86 ASM to C code!\r\n");
|
||||
printf("Initialized!\r\n");
|
||||
}
|
||||
1
src/bootloader/stage2/main.err
Normal file
1
src/bootloader/stage2/main.err
Normal file
@ -0,0 +1 @@
|
||||
main.c(9): Warning! W303: Parameter 'bootDrive' has been defined, but not referenced
|
||||
20
src/bootloader/stage2/stdint.h
Normal file
20
src/bootloader/stage2/stdint.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed long int int32_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
typedef signed long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
|
||||
typedef uint8_t bool;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
222
src/bootloader/stage2/stdio.c
Normal file
222
src/bootloader/stage2/stdio.c
Normal file
@ -0,0 +1,222 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#include "stdio.h"
|
||||
#include "x86.h"
|
||||
|
||||
void putc(char c)
|
||||
{
|
||||
x86_Video_WriteCharTeletype(c, 0);
|
||||
}
|
||||
|
||||
void puts(const char* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
putc(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
#define PRINTF_STATE_NORMAL 0
|
||||
#define PRINTF_STATE_LENGTH 1
|
||||
#define PRINTF_STATE_LENGTH_SHORT 2
|
||||
#define PRINTF_STATE_LENGTH_LONG 3
|
||||
#define PRINTF_STATE_SPEC 4
|
||||
|
||||
#define PRINTF_LENGTH_DEFAULT 0
|
||||
#define PRINTF_LENGTH_SHORT_SHORT 1
|
||||
#define PRINTF_LENGTH_SHORT 2
|
||||
#define PRINTF_LENGTH_LONG 3
|
||||
#define PRINTF_LENGTH_LONG_LONG 4
|
||||
|
||||
|
||||
int* printf_number(int* argp, int length, bool sign, int radix);
|
||||
|
||||
void _cdecl printf(const char* fmt, ...) {
|
||||
int* argp = (int*)&fmt;
|
||||
int state= PRINTF_STATE_NORMAL;
|
||||
int length = PRINTF_LENGTH_DEFAULT;
|
||||
int radix = 10;
|
||||
bool sign = false;
|
||||
|
||||
argp++;
|
||||
|
||||
while (*fmt)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PRINTF_STATE_NORMAL:
|
||||
switch (*fmt)
|
||||
{
|
||||
case '%': state = PRINTF_STATE_NORMAL;
|
||||
break;
|
||||
default: putc(*fmt);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LENGTH:
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'h': length = PRINTF_LENGTH_SHORT;
|
||||
state = PRINTF_STATE_LENGTH_SHORT;
|
||||
break;
|
||||
case 'l': length = PRINTF_LENGTH_LONG;
|
||||
state = PRINTF_STATE_LENGTH_LONG;
|
||||
break;
|
||||
default: goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LENGTH_SHORT:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else goto PRINTF_STATE_SPEC_;
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LENGTH_LONG:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG_LONG;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else goto PRINTF_STATE_SPEC_;
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SPEC:
|
||||
PRINTF_STATE_SPEC_:
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c': putc((char)*argp);
|
||||
argp++;
|
||||
break;
|
||||
|
||||
case 's': puts(*(char***)argp);
|
||||
argp++;
|
||||
break;
|
||||
|
||||
case '%': putc('%');
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i': radix = 10; sign = true;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
|
||||
case 'u': radix = 10; sign = false;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
case 'x':
|
||||
case 'p': radix = 16; sign = false;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
|
||||
case 'o': radix = 8; sign = false;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
|
||||
//ignore invalid specifiers (specs)
|
||||
default: break;
|
||||
}
|
||||
|
||||
//reset state
|
||||
state = PRINTF_STATE_NORMAL;
|
||||
length = PRINTF_LENGTH_DEFAULT;
|
||||
radix = 10;
|
||||
sign = false;
|
||||
break;
|
||||
}
|
||||
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
|
||||
const char g_HexChars[] = "0123456789abcdef";
|
||||
|
||||
int* printf_number(int* argp, int length, bool sign, int radix)
|
||||
{
|
||||
char buffer[32];
|
||||
unsigned long long number;
|
||||
int number_sign = 1;
|
||||
int pos = 0;
|
||||
|
||||
//process length
|
||||
switch (length)
|
||||
{
|
||||
case PRINTF_LENGTH_SHORT_SHORT:
|
||||
case PRINTF_LENGTH_SHORT:
|
||||
case PRINTF_LENGTH_DEFAULT:
|
||||
if (sign)
|
||||
{
|
||||
int n = *argp;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned int*)argp;
|
||||
}
|
||||
argp++;
|
||||
break;
|
||||
|
||||
case PRINTF_LENGTH_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long int n = *(long int*)argp;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long int*)argp;
|
||||
}
|
||||
argp += 2;
|
||||
break;
|
||||
|
||||
case PRINTF_LENGTH_LONG_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long long int n = *(long long int*)argp;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long long*)argp;
|
||||
}
|
||||
argp += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
//number to ASCII conversion
|
||||
do {
|
||||
uint32_t rem;
|
||||
x86_div64_32(number, radix, &number, &rem);
|
||||
buffer[pos++] = g_HexChars[rem];
|
||||
} while (number > 0);
|
||||
|
||||
//add sign
|
||||
if (sign && number_sign < 0) {
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
//print number in reverse order
|
||||
while (--pos >= 0)
|
||||
putc(buffer[pos]);
|
||||
|
||||
return argp;
|
||||
}
|
||||
5
src/bootloader/stage2/stdio.err
Normal file
5
src/bootloader/stage2/stdio.err
Normal file
@ -0,0 +1,5 @@
|
||||
x86.h(22): Error! E1009: Expecting ',' or ';' but found 'x86_Disk_GetDriveParams'
|
||||
stdio.c(100): Warning! W100: Parameter 1 contains inconsistent levels of indirection
|
||||
stdio.c(100): Note! I2003: source conversion type is 'char **'
|
||||
stdio.c(100): Note! I2004: target conversion type is 'char const *'
|
||||
stdio.c(100): Note! I2002: 'puts' defined in: stdio.c(14)
|
||||
10
src/bootloader/stage2/stdio.h
Normal file
10
src/bootloader/stage2/stdio.h
Normal file
@ -0,0 +1,10 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
|
||||
void putc(char c);
|
||||
void puts(const char* str);
|
||||
void _cdecl printf(const char* fmt, ...);
|
||||
102
src/bootloader/stage2/x86.asm
Normal file
102
src/bootloader/stage2/x86.asm
Normal file
@ -0,0 +1,102 @@
|
||||
;/////////////////////;
|
||||
;Nanite OS ;
|
||||
;COPYRIGHT (C) 2024 ;
|
||||
;Tyler McGurrin ;
|
||||
;/////////////////////;
|
||||
bits 16
|
||||
|
||||
section _TEXT class=CODE
|
||||
|
||||
;
|
||||
;void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotentOut, uint32_t* remainderOut);
|
||||
;
|
||||
|
||||
global _x86_div64_32
|
||||
_x86_div64_32
|
||||
;make new call frame
|
||||
push bp ;save old call frame
|
||||
mov bp, sp ;init new call frame
|
||||
|
||||
push bx
|
||||
|
||||
;divide upper 32 bits
|
||||
mov eax, [bp + 4] ;eax is upper 32 bits of divedend
|
||||
mov ecx, [bp + 12] ;ecx is the divisor
|
||||
xor edx, edx
|
||||
div ecx ;eax - quot, edx - remainder
|
||||
|
||||
;store upper 32 bits
|
||||
mov ebx, [bp + 16]
|
||||
mov [bx + 4], eax
|
||||
|
||||
;divide lower 32 bits
|
||||
mov eax, [bp + 4] ;eax is the lower 32 bits of the dividend
|
||||
;edx is old remainder
|
||||
div ecx
|
||||
|
||||
;store results
|
||||
mov [bx], eax
|
||||
mov bx, [bp + 18]
|
||||
mov [bx], edx
|
||||
|
||||
pop bx
|
||||
|
||||
;restore old call frame
|
||||
mov sp, bp
|
||||
pop bp
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
global _x86_Video_WriteCharTeletype
|
||||
_x86_Video_WriteCharTeletype:
|
||||
|
||||
push bp
|
||||
mov bp,sp
|
||||
|
||||
push bx
|
||||
|
||||
mov ah, 0Eh
|
||||
mov al, [bp + 4]
|
||||
mov bh, [bp + 6]
|
||||
|
||||
int 10h
|
||||
|
||||
pop bx
|
||||
|
||||
mov sp, bp
|
||||
pop bp
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
;void _cdecl x86_Disk_Reset(uint8_t drive);
|
||||
;
|
||||
global _x86_Disk_Reset
|
||||
_x86_Disk_Reset:
|
||||
;make new call frame
|
||||
push bp ;save old call frame
|
||||
mov bp, sp ;init new call frame
|
||||
|
||||
|
||||
|
||||
;restore old call frame
|
||||
mov sp, bp
|
||||
pop bp
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
;void _cdecl x86_Disk_Read(uint8_t drive,
|
||||
; uint16_t cylinder,
|
||||
; uint16_t head,
|
||||
; uint16_t sector,
|
||||
; uint8_t count,
|
||||
; uint8_t far * dataout);
|
||||
;
|
||||
;void _cdelc x86_Disk_GetDriveParams(uint8_t drive,
|
||||
; uint8_t* driveTypeOut,
|
||||
; uint16_t* cylindersOut,
|
||||
; uint16_t* sectorsOut,
|
||||
; uint16_t* headsOut);
|
||||
26
src/bootloader/stage2/x86.h
Normal file
26
src/bootloader/stage2/x86.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
|
||||
void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotentOut, uint32_t* remainderOut);
|
||||
|
||||
void _cdecl x86_Video_WriteCharTeletype(char c, uint8_t page);
|
||||
|
||||
void _cdecl x86_Disk_Reset(uint8_t drive);
|
||||
|
||||
void _cdecl x86_Disk_Read(uint8_t drive,
|
||||
uint16_t cylinder,
|
||||
uint16_t head,
|
||||
uint16_t sector,
|
||||
uint8_t count,
|
||||
uint8_t far * dataout);
|
||||
|
||||
void _cdelc x86_Disk_GetDriveParams(uint8_t drive,
|
||||
uint8_t* driveTypeOut,
|
||||
uint16_t* cylindersOut,
|
||||
uint16_t* sectorsOut,
|
||||
uint16_t* headsOut);
|
||||
14
src/kernel/Makefile
Normal file
14
src/kernel/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
BUILD_DIR?=build/
|
||||
ASM?=nasm
|
||||
|
||||
.PHONY: all kernel clean
|
||||
|
||||
all: kernel
|
||||
|
||||
kernel: $(BUILD_DIR)/kernel.bin
|
||||
|
||||
$(BUILD_DIR)/kernel.bin:
|
||||
$(ASM) main.asm -f bin -o $(BUILD_DIR)/kernel.bin
|
||||
|
||||
clean:
|
||||
rm -f $(BUILD_DIR)/kernel.bin
|
||||
50
src/kernel/main.asm
Normal file
50
src/kernel/main.asm
Normal file
@ -0,0 +1,50 @@
|
||||
;/////////////////////;
|
||||
;Nanite OS ;
|
||||
;COPYRIGHT (C) 2024 ;
|
||||
;Tyler McGurrin ;
|
||||
;/////////////////////;
|
||||
org 0x0
|
||||
bits 16
|
||||
|
||||
|
||||
%define ENDL 0x0D, 0x0A
|
||||
|
||||
|
||||
start:
|
||||
; print hello world message
|
||||
mov si, msg_hello
|
||||
call puts
|
||||
|
||||
.halt:
|
||||
cli
|
||||
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
|
||||
|
||||
msg_hello: db 'Loading Kernel...', ENDL, 0
|
||||
2
src/micron/Makefile
Normal file
2
src/micron/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
CC = gcc
|
||||
BUILD_DIR = /build/micron
|
||||
BIN
src/micron/main
Normal file
BIN
src/micron/main
Normal file
Binary file not shown.
232
src/micron/main.c
Normal file
232
src/micron/main.c
Normal file
@ -0,0 +1,232 @@
|
||||
/*----------------*\
|
||||
|Nanite OS |
|
||||
|Copyright (C) 2024|
|
||||
|Tyler McGurrin |
|
||||
\*----------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "tinydir.h"
|
||||
|
||||
//Varible Setup here
|
||||
#define os "Nanite OS"
|
||||
#define version "0.0.1a"
|
||||
#define cursor ":\\>"
|
||||
#define hostname "[NOT IMPLEMENTED YET]"
|
||||
#define os_logo " _ _ _ _ _____ _____ \n| \\ | | (_) | | _ / ___|\n| \\| | __ _ _ __ _| |_ ___ | | | \\ `--. \n| . ` |/ _` | '_ \\| | __/ _ \\ | | | |`--. \\\n| |\\ | (_| | | | | | || __/ \\ \\_/ /\\__/ /\n\\_| \\_/\\__,_|_| |_|_|\\__\\___| \\___/\\____/ \n"
|
||||
#define shell_logo " __ __ _ __ __ \n | \\/ (_) ___ _ __ ___ _ __ \\ \\ \\ \\ \n | |\\/| | |/ __| '__/ _ \\| '_ \\(_) \\ \\ \\\n | | | | | (__| | | (_) | | | |_ \\ \\ / /\n |_| |_|_|\\___|_| \\___/|_| |_(_) \\_\\/_/ \n \n"
|
||||
int invalid_command = 0;
|
||||
int command_list_length = 10; //does not NEED to match command list's length just helps with slower machines to keep this small and it can get buggy if too large
|
||||
int history_length = {0};
|
||||
int max_files = 200;
|
||||
char command_list[][15] = {"help","version","clear", "uname", "exit", "dir", "fetch", "time", "exec"};
|
||||
char buffer[15][255];
|
||||
char program_buffer[30][100];
|
||||
char prog_buffer2;
|
||||
char history[][255];
|
||||
char time_buffer[80];
|
||||
char exec_cmd_operand_list[15][15] = {"--help", "--nogui"};
|
||||
char exec_cmd_dir_buffer[][255];
|
||||
|
||||
|
||||
int main() {
|
||||
printf("Micron Shell Version " version " Starting...\n");
|
||||
|
||||
stage2();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stage2() {
|
||||
printf("Done Loading Shell!\n");
|
||||
printf("Currently Implemtented Commands:\n");
|
||||
for(int i = 0; i < command_list_length; i++) {
|
||||
printf("%s ", &command_list[i]);}
|
||||
printf("\n");
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cursor_loop() {
|
||||
printf(cursor);
|
||||
scanf("%s", &buffer);
|
||||
//Command detection shiz
|
||||
if (strcmp(buffer[0],command_list[0]) == 0) {help_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[1]) == 0) {version_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[2]) == 0) {clear_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[3]) == 0) {uname_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[4]) == 0) {exit_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[5]) == 0) {dir_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[6]) == 0) {fetch_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[7]) == 0) {time_cmd();}
|
||||
else if (strcmp(buffer[0],command_list[8]) == 0) {exec_cmd();}
|
||||
else {printf("Mircon: %s: Command not Found!\n", &buffer); clear_buffer();}
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Bulit in commands
|
||||
int help_cmd() {
|
||||
printf("Built-in Commands:\n");
|
||||
for(int i = 0; i < command_list_length; i++) {
|
||||
printf("%s ", &command_list[i]);}
|
||||
printf("\n");
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int version_cmd() {
|
||||
printf(shell_logo);
|
||||
printf("Version %s Made by Tyler McGurrin\nCopyright (C) 2024\n", &version);
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int clear_cmd() {
|
||||
for(int i = 0; i < 2500; i++) {
|
||||
printf("\n");
|
||||
}
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int uname_cmd() {
|
||||
printf("%s\n", &os);
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int exit_cmd() {
|
||||
printf("Exiting Micron Shell...\n");
|
||||
exit(0);
|
||||
}
|
||||
int dir_cmd() {
|
||||
tinydir_dir dir;
|
||||
tinydir_open(&dir, "./");
|
||||
|
||||
while (dir.has_next)
|
||||
{
|
||||
tinydir_file file;
|
||||
tinydir_readfile(&dir, &file);
|
||||
|
||||
printf("%s", file.name);
|
||||
if (file.is_dir)
|
||||
{
|
||||
printf("/ DIR");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
tinydir_next(&dir);
|
||||
}
|
||||
|
||||
tinydir_close(&dir);
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int fetch_cmd() {
|
||||
printf("Operating System: %s\nShell: Micron %s\nHostname: %s\n",os,version,hostname);
|
||||
time_t t = time(NULL);
|
||||
printf("UTC Time: %s", asctime(gmtime(&t)));
|
||||
printf("Local Time: %s", asctime(localtime(&t)));
|
||||
printf(os_logo);
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int time_cmd() {
|
||||
time_t t = time(NULL);
|
||||
printf("UTC: %s", asctime(gmtime(&t)));
|
||||
printf("Local: %s", asctime(localtime(&t)));
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int exec_cmd() {
|
||||
if (strcmp(buffer[1], exec_cmd_operand_list[0]) == 0) {exec_cmd_help();}
|
||||
else {exec_cmd_gui(); clear_buffer();}
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Command Handlers
|
||||
|
||||
//Exec Handlers
|
||||
int exec_cmd_gui() {
|
||||
printf("\nExec:>");
|
||||
scanf("%s", &program_buffer);
|
||||
if (strcmp(program_buffer[0],command_list[0]) == 0) {help_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[1]) == 0) {version_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[2]) == 0) {clear_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[3]) == 0) {uname_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[4]) == 0) {exit_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[5]) == 0) {dir_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[6]) == 0) {fetch_cmd();}
|
||||
else if (strcmp(program_buffer[0],command_list[7]) == 0) {time_cmd();}
|
||||
else {exec_cmd_dir();}
|
||||
//if (exec_cmd_dir_buffer){printf("Exec: %s: Executible not Found!\n", &buffer); clear_buffer();}
|
||||
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_cmd_help() {
|
||||
printf("Usage [Operands Like: ");
|
||||
for(int i = 0; i < command_list_length; i++) {
|
||||
printf("%s ", &exec_cmd_operand_list[i]);}
|
||||
printf("]\n");
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int exec_cmd_dir() {
|
||||
tinydir_dir dir;
|
||||
tinydir_open(&dir, "./");
|
||||
|
||||
while (dir.has_next)
|
||||
{
|
||||
tinydir_file file;
|
||||
tinydir_readfile(&dir, &file);
|
||||
|
||||
for(int i = 0; i < max_files; i++) {
|
||||
buffer[i][255] = NULL;}
|
||||
if (file.is_dir)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for(int i = 0; i < max_files; i++) {
|
||||
if (strcmp(program_buffer,file.name) == 0) {
|
||||
printf("Loading program...");
|
||||
strcat(prog_buffer2, "./");
|
||||
strcat(prog_buffer2, program_buffer);
|
||||
prog_load();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
}
|
||||
printf("Exec: %s: No Executible found!\n", &program_buffer);
|
||||
tinydir_next(&dir);
|
||||
tinydir_close(&dir);
|
||||
clear_buffer();
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Extra Tools (Not executible via shell)
|
||||
int clear_buffer() {
|
||||
|
||||
for(int i = 0; i < command_list_length; i++) {
|
||||
buffer[i][255] = NULL;}
|
||||
free(prog_buffer2);
|
||||
cursor_loop();
|
||||
return 0;
|
||||
}
|
||||
int prog_load() {
|
||||
system(prog_buffer2);
|
||||
exit(0);
|
||||
}
|
||||
848
src/micron/tinydir.h
Normal file
848
src/micron/tinydir.h
Normal file
@ -0,0 +1,848 @@
|
||||
/*
|
||||
Copyright (c) 2013-2021, tinydir authors:
|
||||
- Cong Xu
|
||||
- Lautis Sun
|
||||
- Baudouin Feildel
|
||||
- Andargor <andargor@yahoo.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TINYDIR_H
|
||||
#define TINYDIR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if ((defined _UNICODE) && !(defined UNICODE))
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#if ((defined UNICODE) && !(defined _UNICODE))
|
||||
#define _UNICODE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _MSC_VER
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <tchar.h>
|
||||
# pragma warning(push)
|
||||
# pragma warning (disable : 4996)
|
||||
#else
|
||||
# include <dirent.h>
|
||||
# include <libgen.h>
|
||||
# include <sys/stat.h>
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
# include <tchar.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* types */
|
||||
|
||||
/* Windows UNICODE wide character support */
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
# define _tinydir_char_t TCHAR
|
||||
# define TINYDIR_STRING(s) _TEXT(s)
|
||||
# define _tinydir_strlen _tcslen
|
||||
# define _tinydir_strcpy _tcscpy
|
||||
# define _tinydir_strcat _tcscat
|
||||
# define _tinydir_strcmp _tcscmp
|
||||
# define _tinydir_strrchr _tcsrchr
|
||||
# define _tinydir_strncmp _tcsncmp
|
||||
#else
|
||||
# define _tinydir_char_t char
|
||||
# define TINYDIR_STRING(s) s
|
||||
# define _tinydir_strlen strlen
|
||||
# define _tinydir_strcpy strcpy
|
||||
# define _tinydir_strcat strcat
|
||||
# define _tinydir_strcmp strcmp
|
||||
# define _tinydir_strrchr strrchr
|
||||
# define _tinydir_strncmp strncmp
|
||||
#endif
|
||||
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
# include <windows.h>
|
||||
# define _TINYDIR_PATH_MAX MAX_PATH
|
||||
#elif defined __linux__
|
||||
# include <limits.h>
|
||||
# ifdef PATH_MAX
|
||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
||||
# endif
|
||||
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
# include <sys/param.h>
|
||||
# if defined(BSD)
|
||||
# include <limits.h>
|
||||
# ifdef PATH_MAX
|
||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _TINYDIR_PATH_MAX
|
||||
#define _TINYDIR_PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* extra chars for the "\\*" mask */
|
||||
# define _TINYDIR_PATH_EXTRA 2
|
||||
#else
|
||||
# define _TINYDIR_PATH_EXTRA 0
|
||||
#endif
|
||||
|
||||
#define _TINYDIR_FILENAME_MAX 256
|
||||
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
#define _TINYDIR_DRIVE_MAX 3
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _TINYDIR_FUNC static __inline
|
||||
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
||||
# define _TINYDIR_FUNC static __inline__
|
||||
#elif defined(__cplusplus)
|
||||
# define _TINYDIR_FUNC static inline
|
||||
#elif defined(__GNUC__)
|
||||
/* Suppress unused function warning */
|
||||
# define _TINYDIR_FUNC __attribute__((unused)) static
|
||||
#else
|
||||
# define _TINYDIR_FUNC static
|
||||
#endif
|
||||
|
||||
#if defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
|
||||
#ifdef _MSC_VER
|
||||
# define _TINYDIR_CDECL __cdecl
|
||||
#else
|
||||
# define _TINYDIR_CDECL __attribute__((cdecl))
|
||||
#endif
|
||||
#else
|
||||
# define _TINYDIR_CDECL
|
||||
#endif
|
||||
|
||||
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
|
||||
#ifdef TINYDIR_USE_READDIR_R
|
||||
|
||||
/* readdir_r is a POSIX-only function, and may not be available under various
|
||||
* environments/settings, e.g. MinGW. Use readdir fallback */
|
||||
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
|
||||
_POSIX_SOURCE
|
||||
# define _TINYDIR_HAS_READDIR_R
|
||||
#endif
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
# define _TINYDIR_HAS_FPATHCONF
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if _BSD_SOURCE || _SVID_SOURCE || \
|
||||
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
||||
# define _TINYDIR_HAS_DIRFD
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
|
||||
defined _PC_NAME_MAX
|
||||
# define _TINYDIR_USE_FPATHCONF
|
||||
#endif
|
||||
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
|
||||
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
|
||||
# define _TINYDIR_USE_READDIR
|
||||
#endif
|
||||
|
||||
/* Use readdir by default */
|
||||
#else
|
||||
# define _TINYDIR_USE_READDIR
|
||||
#endif
|
||||
|
||||
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
|
||||
#ifndef _MSC_VER
|
||||
#if (defined __MINGW32__) && (defined _UNICODE)
|
||||
#define _TINYDIR_DIR _WDIR
|
||||
#define _tinydir_dirent _wdirent
|
||||
#define _tinydir_opendir _wopendir
|
||||
#define _tinydir_readdir _wreaddir
|
||||
#define _tinydir_closedir _wclosedir
|
||||
#else
|
||||
#define _TINYDIR_DIR DIR
|
||||
#define _tinydir_dirent dirent
|
||||
#define _tinydir_opendir opendir
|
||||
#define _tinydir_readdir readdir
|
||||
#define _tinydir_closedir closedir
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
|
||||
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
|
||||
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
|
||||
#else
|
||||
#error "Either define both alloc and free or none of them!"
|
||||
#endif
|
||||
|
||||
#if !defined(_TINYDIR_MALLOC)
|
||||
#define _TINYDIR_MALLOC(_size) malloc(_size)
|
||||
#define _TINYDIR_FREE(_ptr) free(_ptr)
|
||||
#endif /* !defined(_TINYDIR_MALLOC) */
|
||||
|
||||
typedef struct tinydir_file
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
|
||||
_tinydir_char_t *extension;
|
||||
int is_dir;
|
||||
int is_reg;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifdef __MINGW32__
|
||||
struct _stat _s;
|
||||
#else
|
||||
struct stat _s;
|
||||
#endif
|
||||
#endif
|
||||
} tinydir_file;
|
||||
|
||||
typedef struct tinydir_dir
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
int has_next;
|
||||
size_t n_files;
|
||||
|
||||
tinydir_file *_files;
|
||||
#ifdef _MSC_VER
|
||||
HANDLE _h;
|
||||
WIN32_FIND_DATA _f;
|
||||
#else
|
||||
_TINYDIR_DIR *_d;
|
||||
struct _tinydir_dirent *_e;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
struct _tinydir_dirent *_ep;
|
||||
#endif
|
||||
#endif
|
||||
} tinydir_dir;
|
||||
|
||||
|
||||
/* declarations */
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
void tinydir_close(tinydir_dir *dir);
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_next(tinydir_dir *dir);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
void _tinydir_get_ext(tinydir_file *file);
|
||||
_TINYDIR_FUNC
|
||||
int _TINYDIR_CDECL _tinydir_file_cmp(const void *a, const void *b);
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
_TINYDIR_FUNC
|
||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* definitions*/
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
int error;
|
||||
int size; /* using int size */
|
||||
#endif
|
||||
#else
|
||||
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
|
||||
#endif
|
||||
_tinydir_char_t *pathp;
|
||||
|
||||
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialise dir */
|
||||
dir->_files = NULL;
|
||||
#ifdef _MSC_VER
|
||||
dir->_h = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
dir->_d = NULL;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
dir->_ep = NULL;
|
||||
#endif
|
||||
#endif
|
||||
tinydir_close(dir);
|
||||
|
||||
_tinydir_strcpy(dir->path, path);
|
||||
/* Remove trailing slashes */
|
||||
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
|
||||
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
|
||||
{
|
||||
*pathp = TINYDIR_STRING('\0');
|
||||
pathp++;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
_tinydir_strcpy(path_buf, dir->path);
|
||||
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
|
||||
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
|
||||
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
|
||||
#else
|
||||
dir->_h = FindFirstFile(path_buf, &dir->_f);
|
||||
#endif
|
||||
if (dir->_h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
errno = ENOENT;
|
||||
#else
|
||||
dir->_d = _tinydir_opendir(path);
|
||||
if (dir->_d == NULL)
|
||||
{
|
||||
#endif
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* read first file */
|
||||
dir->has_next = 1;
|
||||
#ifndef _MSC_VER
|
||||
#ifdef _TINYDIR_USE_READDIR
|
||||
dir->_e = _tinydir_readdir(dir->_d);
|
||||
#else
|
||||
/* allocate dirent buffer for readdir_r */
|
||||
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
|
||||
if (size == -1) return -1;
|
||||
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
|
||||
if (dir->_ep == NULL) return -1;
|
||||
|
||||
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
|
||||
if (error != 0) return -1;
|
||||
#endif
|
||||
if (dir->_e == NULL)
|
||||
{
|
||||
dir->has_next = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
tinydir_close(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
|
||||
{
|
||||
/* Count the number of files first, to pre-allocate the files array */
|
||||
size_t n_files = 0;
|
||||
if (tinydir_open(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
while (dir->has_next)
|
||||
{
|
||||
n_files++;
|
||||
if (tinydir_next(dir) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
tinydir_close(dir);
|
||||
|
||||
if (n_files == 0 || tinydir_open(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->n_files = 0;
|
||||
dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
|
||||
if (dir->_files == NULL)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
while (dir->has_next)
|
||||
{
|
||||
tinydir_file *p_file;
|
||||
dir->n_files++;
|
||||
|
||||
p_file = &dir->_files[dir->n_files - 1];
|
||||
if (tinydir_readfile(dir, p_file) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (tinydir_next(dir) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Just in case the number of files has changed between the first and
|
||||
second reads, terminate without writing into unallocated memory */
|
||||
if (dir->n_files == n_files)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
tinydir_close(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
void tinydir_close(tinydir_dir *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(dir->path, 0, sizeof(dir->path));
|
||||
dir->has_next = 0;
|
||||
dir->n_files = 0;
|
||||
_TINYDIR_FREE(dir->_files);
|
||||
dir->_files = NULL;
|
||||
#ifdef _MSC_VER
|
||||
if (dir->_h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(dir->_h);
|
||||
}
|
||||
dir->_h = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
if (dir->_d)
|
||||
{
|
||||
_tinydir_closedir(dir->_d);
|
||||
}
|
||||
dir->_d = NULL;
|
||||
dir->_e = NULL;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
_TINYDIR_FREE(dir->_ep);
|
||||
dir->_ep = NULL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_next(tinydir_dir *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!dir->has_next)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
if (FindNextFile(dir->_h, &dir->_f) == 0)
|
||||
#else
|
||||
#ifdef _TINYDIR_USE_READDIR
|
||||
dir->_e = _tinydir_readdir(dir->_d);
|
||||
#else
|
||||
if (dir->_ep == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (dir->_e == NULL)
|
||||
#endif
|
||||
{
|
||||
dir->has_next = 0;
|
||||
#ifdef _MSC_VER
|
||||
if (GetLastError() != ERROR_SUCCESS &&
|
||||
GetLastError() != ERROR_NO_MORE_FILES)
|
||||
{
|
||||
tinydir_close(dir);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
||||
{
|
||||
const _tinydir_char_t *filename;
|
||||
if (dir == NULL || file == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
if (dir->_h == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
if (dir->_e == NULL)
|
||||
#endif
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
filename =
|
||||
#ifdef _MSC_VER
|
||||
dir->_f.cFileName;
|
||||
#else
|
||||
dir->_e->d_name;
|
||||
#endif
|
||||
if (_tinydir_strlen(dir->path) +
|
||||
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
|
||||
_TINYDIR_PATH_MAX)
|
||||
{
|
||||
/* the path for the file will be too long */
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tinydir_strcpy(file->path, dir->path);
|
||||
if (_tinydir_strcmp(dir->path, TINYDIR_STRING("/")) != 0)
|
||||
_tinydir_strcat(file->path, TINYDIR_STRING("/"));
|
||||
_tinydir_strcpy(file->name, filename);
|
||||
_tinydir_strcat(file->path, filename);
|
||||
#ifndef _MSC_VER
|
||||
#ifdef __MINGW32__
|
||||
if (_tstat(
|
||||
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \
|
||||
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|
||||
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|
||||
|| ((defined __APPLE__) && (defined __MACH__)) \
|
||||
|| (defined BSD)
|
||||
if (lstat(
|
||||
#else
|
||||
if (stat(
|
||||
#endif
|
||||
file->path, &file->_s) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
_tinydir_get_ext(file);
|
||||
|
||||
file->is_dir =
|
||||
#ifdef _MSC_VER
|
||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
#else
|
||||
S_ISDIR(file->_s.st_mode);
|
||||
#endif
|
||||
file->is_reg =
|
||||
#ifdef _MSC_VER
|
||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
|
||||
(
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
|
||||
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
|
||||
#endif
|
||||
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
|
||||
#endif
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
|
||||
#else
|
||||
S_ISREG(file->_s.st_mode);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
|
||||
{
|
||||
if (dir == NULL || file == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (i >= dir->n_files)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
|
||||
_tinydir_get_ext(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
if (dir == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (i >= dir->n_files || !dir->_files[i].is_dir)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tinydir_strcpy(path, dir->_files[i].path);
|
||||
tinydir_close(dir);
|
||||
if (tinydir_open_sorted(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open a single file given its path */
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
|
||||
{
|
||||
tinydir_dir dir;
|
||||
int result = 0;
|
||||
int found = 0;
|
||||
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t file_name_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t *dir_name;
|
||||
_tinydir_char_t *base_name;
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
|
||||
#endif
|
||||
|
||||
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the parent path */
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
|
||||
errno = _tsplitpath_s(
|
||||
path,
|
||||
drive_buf, _TINYDIR_DRIVE_MAX,
|
||||
dir_name_buf, _TINYDIR_FILENAME_MAX,
|
||||
file_name_buf, _TINYDIR_FILENAME_MAX,
|
||||
ext_buf, _TINYDIR_FILENAME_MAX);
|
||||
#else
|
||||
_tsplitpath(
|
||||
path,
|
||||
drive_buf,
|
||||
dir_name_buf,
|
||||
file_name_buf,
|
||||
ext_buf);
|
||||
#endif
|
||||
|
||||
if (errno)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _splitpath_s not work fine with only filename and widechar support */
|
||||
#ifdef _UNICODE
|
||||
if (drive_buf[0] == L'\xFEFE')
|
||||
drive_buf[0] = '\0';
|
||||
if (dir_name_buf[0] == L'\xFEFE')
|
||||
dir_name_buf[0] = '\0';
|
||||
#endif
|
||||
|
||||
/* Emulate the behavior of dirname by returning "." for dir name if it's
|
||||
empty */
|
||||
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
|
||||
{
|
||||
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
|
||||
}
|
||||
/* Concatenate the drive letter and dir name to form full dir name */
|
||||
_tinydir_strcat(drive_buf, dir_name_buf);
|
||||
dir_name = drive_buf;
|
||||
/* Concatenate the file name and extension to form base name */
|
||||
_tinydir_strcat(file_name_buf, ext_buf);
|
||||
base_name = file_name_buf;
|
||||
#else
|
||||
_tinydir_strcpy(dir_name_buf, path);
|
||||
dir_name = dirname(dir_name_buf);
|
||||
_tinydir_strcpy(file_name_buf, path);
|
||||
base_name = basename(file_name_buf);
|
||||
#endif
|
||||
|
||||
/* Special case: if the path is a root dir, open the parent dir as the file */
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
if (_tinydir_strlen(base_name) == 0)
|
||||
#else
|
||||
if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
|
||||
#endif
|
||||
{
|
||||
memset(file, 0, sizeof * file);
|
||||
file->is_dir = 1;
|
||||
file->is_reg = 0;
|
||||
_tinydir_strcpy(file->path, dir_name);
|
||||
file->extension = file->path + _tinydir_strlen(file->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the parent directory */
|
||||
if (tinydir_open(&dir, dir_name) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read through the parent directory and look for the file */
|
||||
while (dir.has_next)
|
||||
{
|
||||
if (tinydir_readfile(&dir, file) == -1)
|
||||
{
|
||||
result = -1;
|
||||
goto bail;
|
||||
}
|
||||
if (_tinydir_strcmp(file->name, base_name) == 0)
|
||||
{
|
||||
/* File found */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
tinydir_next(&dir);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
result = -1;
|
||||
errno = ENOENT;
|
||||
}
|
||||
|
||||
bail:
|
||||
tinydir_close(&dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
void _tinydir_get_ext(tinydir_file *file)
|
||||
{
|
||||
_tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
|
||||
if (period == NULL)
|
||||
{
|
||||
file->extension = &(file->name[_tinydir_strlen(file->name)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
file->extension = period + 1;
|
||||
}
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int _TINYDIR_CDECL _tinydir_file_cmp(const void *a, const void *b)
|
||||
{
|
||||
const tinydir_file *fa = (const tinydir_file *)a;
|
||||
const tinydir_file *fb = (const tinydir_file *)b;
|
||||
if (fa->is_dir != fb->is_dir)
|
||||
{
|
||||
return -(fa->is_dir - fb->is_dir);
|
||||
}
|
||||
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
/*
|
||||
The following authored by Ben Hutchings <ben@decadent.org.uk>
|
||||
from https://womble.decadent.org.uk/readdir_r-advisory.html
|
||||
*/
|
||||
/* Calculate the required buffer size (in bytes) for directory *
|
||||
* entries read from the given directory handle. Return -1 if this *
|
||||
* this cannot be done. *
|
||||
* *
|
||||
* This code does not trust values of NAME_MAX that are less than *
|
||||
* 255, since some systems (including at least HP-UX) incorrectly *
|
||||
* define it to be a smaller value. */
|
||||
_TINYDIR_FUNC
|
||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
|
||||
{
|
||||
long name_max;
|
||||
size_t name_end;
|
||||
/* parameter may be unused */
|
||||
(void)dirp;
|
||||
|
||||
#if defined _TINYDIR_USE_FPATHCONF
|
||||
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
|
||||
if (name_max == -1)
|
||||
#if defined(NAME_MAX)
|
||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||
#else
|
||||
return (size_t)(-1);
|
||||
#endif
|
||||
#elif defined(NAME_MAX)
|
||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||
#else
|
||||
#error "buffer size for readdir_r cannot be determined"
|
||||
#endif
|
||||
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
|
||||
return (name_end > sizeof(struct _tinydir_dirent) ?
|
||||
name_end : sizeof(struct _tinydir_dirent));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
# if defined (_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
183
tools/fat/fat.c
Normal file
183
tools/fat/fat.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef uint8_t bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BootJumpInstruction[3];
|
||||
uint8_t OemIdentifier[8];
|
||||
uint16_t BytesPerSector;
|
||||
uint8_t SectorsPerCluster;
|
||||
uint16_t ReservedSectors;
|
||||
uint8_t FatCount;
|
||||
uint16_t DirEntryCount;
|
||||
uint16_t TotalSectors;
|
||||
uint8_t MediaDescriptorType;
|
||||
uint16_t SectorsPerFat;
|
||||
uint16_t SectorsPerTrack;
|
||||
uint16_t Heads;
|
||||
uint32_t HiddenSectors;
|
||||
uint32_t LargeSectorCount;
|
||||
|
||||
//Extended Boot Record
|
||||
uint8_t DriveNumber;
|
||||
uint8_t _Reserved;
|
||||
uint8_t Signature;
|
||||
uint32_t VolumeId; //Serial Can be whatever
|
||||
uint8_t VolumeLabel[11]; //11 Bytes MUST Be padded with spaces!
|
||||
uint8_t SystemId[8]; //8 Bytes padded with spaces (use MSWIN4.1 for best compatibility!)
|
||||
|
||||
} __attribute__((packed)) BootSector;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Name[11];
|
||||
uint8_t Attributes;
|
||||
uint8_t _Reserved;
|
||||
uint8_t CreatedTimeTenths;
|
||||
uint16_t CreatedTime;
|
||||
uint16_t CreatedDate;
|
||||
uint16_t AccessedDate;
|
||||
uint16_t FirstClusterHigh;
|
||||
uint16_t ModifiedTime;
|
||||
uint16_t ModifiedDate;
|
||||
uint16_t FirstClusterLow;
|
||||
uint32_t Size;
|
||||
|
||||
} __attribute__((packed)) DirectoryEntry;
|
||||
|
||||
BootSector g_BootSector;
|
||||
uint8_t* g_Fat = NULL;
|
||||
DirectoryEntry* g_RootDirectory = NULL;
|
||||
uint32_t g_RootDirectoryEnd;
|
||||
|
||||
bool readBootSector(FILE* disk)
|
||||
{
|
||||
return fread(&g_BootSector, sizeof(g_BootSector), 1, disk) > 0;
|
||||
}
|
||||
|
||||
bool readSectors(FILE* disk, uint32_t lba, uint32_t count, void* bufferout)
|
||||
{
|
||||
bool ok = true;
|
||||
ok = ok && (fseek(disk, lba * g_BootSector.BytesPerSector, SEEK_SET) == 0);
|
||||
ok = ok && (fread(bufferout, g_BootSector.BytesPerSector, count, disk) == count);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool readFat(FILE* disk)
|
||||
{
|
||||
g_Fat = (uint8_t*) malloc(g_BootSector.SectorsPerFat * g_BootSector.BytesPerSector);
|
||||
return readSectors(disk, g_BootSector.ReservedSectors, g_BootSector.SectorsPerFat, g_Fat);
|
||||
}
|
||||
|
||||
bool readRootDirectory(FILE* disk)
|
||||
{
|
||||
uint32_t lba = g_BootSector.ReservedSectors + g_BootSector.SectorsPerFat * g_BootSector.FatCount;
|
||||
uint32_t size = sizeof(DirectoryEntry) * g_BootSector.DirEntryCount;
|
||||
uint32_t sector = (size / g_BootSector.BytesPerSector);
|
||||
if (size % g_BootSector.BytesPerSector > 0)
|
||||
sector++;
|
||||
|
||||
g_RootDirectoryEnd = lba + sector;
|
||||
g_RootDirectory = (DirectoryEntry*) malloc(sector * g_BootSector.BytesPerSector);
|
||||
return readSectors(disk, lba, sector, g_RootDirectory);
|
||||
}
|
||||
|
||||
DirectoryEntry* findFile(const char* name)
|
||||
{
|
||||
for (uint32_t i = 0; i < g_BootSector.DirEntryCount; i++)
|
||||
{
|
||||
if (memcmp(name, g_RootDirectory[i].Name, 11) == 0)
|
||||
return &g_RootDirectory[i];
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool readFile(DirectoryEntry* fileEntry, FILE* disk, uint8_t* outputBuffer)
|
||||
{
|
||||
bool ok = true;
|
||||
uint16_t currentCluster = fileEntry->FirstClusterLow;
|
||||
|
||||
do {
|
||||
uint32_t lba = g_RootDirectoryEnd + (currentCluster - 2) * g_BootSector.SectorsPerCluster;
|
||||
ok = ok && readSectors(disk, lba, g_BootSector.SectorsPerCluster, outputBuffer);
|
||||
outputBuffer += g_BootSector.SectorsPerCluster * g_BootSector.BytesPerSector;
|
||||
|
||||
uint32_t fatIndex = currentCluster * 3 / 2;
|
||||
if (currentCluster % 2 == 0)
|
||||
currentCluster = (*(uint16_t*)(g_Fat + fatIndex)) & 0x0FFF;
|
||||
else
|
||||
currentCluster = (*(uint16_t*)(g_Fat + fatIndex)) >> 4;
|
||||
|
||||
} while (ok && currentCluster < 0x0FF8);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 3){
|
||||
printf("Syntax: %s <disk image> <file name>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* disk = fopen(argv[1], "rb");
|
||||
if (!disk) {
|
||||
fprintf(stderr, "Cannot open disk image %s!\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!readBootSector(disk)) {
|
||||
fprintf(stderr, "Could not read boot sector!\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (!readFat(disk)) {
|
||||
fprintf(stderr, "Could not read FAT!\n");
|
||||
free(g_Fat);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (!readRootDirectory(disk)) {
|
||||
fprintf(stderr, "Could not read root!\n");
|
||||
free(g_Fat);
|
||||
free(g_RootDirectory);
|
||||
return -4;
|
||||
}
|
||||
|
||||
DirectoryEntry* fileEntry = findFile(argv[2]);
|
||||
if (!fileEntry) {
|
||||
fprintf(stderr, "Could not locate file %s!\n", argv[2]);
|
||||
free(g_Fat);
|
||||
free(g_RootDirectory);
|
||||
return -5;
|
||||
}
|
||||
|
||||
uint8_t* buffer = (uint8_t*) malloc(fileEntry->Size + g_BootSector.BytesPerSector);
|
||||
if (!readFile(fileEntry, disk, buffer)) {
|
||||
fprintf(stderr, "Could not read file %s!\n", argv[2]);
|
||||
free(g_Fat);
|
||||
free(g_RootDirectory);
|
||||
free(buffer);
|
||||
return -5;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fileEntry->Size; i++)
|
||||
{
|
||||
if (isprint(buffer[i])) fputc(buffer[i], stdout);
|
||||
//else printf("<%02x>", buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
free(g_Fat);
|
||||
free(g_RootDirectory);
|
||||
return 0;
|
||||
}
|
||||
31
write.sh
Normal file
31
write.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo ------------
|
||||
echo COMPILING OS
|
||||
echo ------------
|
||||
|
||||
sudo make
|
||||
|
||||
echo ---------
|
||||
echo Finished!
|
||||
echo ---------
|
||||
read -p "Do you want to write the IMG to Floppy? (/dev/sdb) (Y/n) " yn
|
||||
|
||||
case $yn in
|
||||
y )
|
||||
echo ---------------------
|
||||
echo Writing IMG to Floppy
|
||||
echo ---------------------
|
||||
|
||||
sudo dd if=./build/main_floppy.img of=/dev/sdb
|
||||
|
||||
echo ---------
|
||||
echo Finished!
|
||||
echo ---------
|
||||
|
||||
;;
|
||||
n ) echo exiting...;
|
||||
exit;;
|
||||
* ) echo invalid response;
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user