feat(loader): logger print time
This commit is contained in:
parent
fe5fc658b3
commit
fb51cf602a
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2020, d0p1
|
Copyright (c) 2024, d0p1
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
|
@ -93,6 +93,8 @@ _start:
|
||||||
xor bx, bx
|
xor bx, bx
|
||||||
call fat_load_binary
|
call fat_load_binary
|
||||||
|
|
||||||
|
mov dl, [drive_number]
|
||||||
|
|
||||||
jmp 0x0:LOADER_BASE
|
jmp 0x0:LOADER_BASE
|
||||||
|
|
||||||
.error_not_found:
|
.error_not_found:
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
include '../common/const.inc'
|
include '../common/const.inc'
|
||||||
include '../common/macro.inc'
|
include '../common/macro.inc'
|
||||||
|
include '../common/bios.inc'
|
||||||
|
include '../common/mbr.inc'
|
||||||
|
|
||||||
org MBR_BASE
|
org MBR_BASE
|
||||||
cli
|
cli
|
||||||
|
@ -19,9 +21,60 @@
|
||||||
rep movsw
|
rep movsw
|
||||||
jmp 0x0:start
|
jmp 0x0:start
|
||||||
start:
|
start:
|
||||||
; TODO: read partition table and load bootable one.
|
; set LBA
|
||||||
|
mov ah, 0x41
|
||||||
|
mov bx, 0x55AA
|
||||||
|
mov dl, 0x80
|
||||||
|
int 0x13
|
||||||
|
jc .error_lba
|
||||||
|
lea ecx, [PT1]
|
||||||
|
.loop:
|
||||||
|
mov al, byte [ecx]
|
||||||
|
bt ax, 7
|
||||||
|
jc .found
|
||||||
|
lea eax, [PT4]
|
||||||
|
test eax, ecx
|
||||||
|
je .error_no_bootable
|
||||||
|
add cx, 0xF
|
||||||
|
jmp .loop
|
||||||
|
.found:
|
||||||
|
mov eax, dword [ecx + Partition.lba]
|
||||||
|
mov [disk_packet_lba], eax
|
||||||
|
mov si, disk_packet
|
||||||
|
mov ah, 0x42
|
||||||
|
mov dl, 0x80
|
||||||
|
int 13
|
||||||
|
jc .error_load
|
||||||
|
jmp 0x0:BOOTSECT_BASE
|
||||||
|
.error_lba:
|
||||||
|
mov si, msg_error_lba
|
||||||
|
jmp .error_print
|
||||||
|
.error_no_bootable:
|
||||||
|
mov si, msg_error_bootable
|
||||||
|
jmp .error_print
|
||||||
|
.error_load:
|
||||||
|
mov si, msg_error_load
|
||||||
|
.error_print:
|
||||||
|
call bios_print
|
||||||
|
.end:
|
||||||
|
hlt
|
||||||
|
jmp $
|
||||||
|
|
||||||
times 436-($-$$) db 0x90
|
disk_packet:
|
||||||
|
db 0x10
|
||||||
|
db 0
|
||||||
|
dw 1
|
||||||
|
dw BOOTSECT_BASE
|
||||||
|
dw 0x0
|
||||||
|
disk_packet_lba:
|
||||||
|
dd 0x0
|
||||||
|
dw 0x0
|
||||||
|
|
||||||
|
msg_error_lba db "We don't support CHS", CR, LF, 0
|
||||||
|
msg_error_bootable db "No bootable device found", CR, LF, 0
|
||||||
|
msg_error_load db "Can't load partition", CR, LF, 0
|
||||||
|
|
||||||
|
rb MBR_BASE+0x1a8-$
|
||||||
UID db 'STUPIDDISK'
|
UID db 'STUPIDDISK'
|
||||||
; partition table
|
; partition table
|
||||||
PT1 db 16 dup(0)
|
PT1 db 16 dup(0)
|
||||||
|
|
|
@ -10,6 +10,9 @@ DISK_BUFFER = 0x8000
|
||||||
KERNEL_PRELOAD = 0xF000
|
KERNEL_PRELOAD = 0xF000
|
||||||
STACK_TOP = 0x7000
|
STACK_TOP = 0x7000
|
||||||
|
|
||||||
|
; ---------- Magic ------------
|
||||||
|
STPDBOOT_MAGIC = 0x53545044
|
||||||
|
|
||||||
; ---------- Video ------------
|
; ---------- Video ------------
|
||||||
VIDEO_WIDTH = 1024
|
VIDEO_WIDTH = 1024
|
||||||
VIDEO_HEIGHT = 768
|
VIDEO_HEIGHT = 768
|
||||||
|
|
15
boot/common/mbr.inc
Normal file
15
boot/common/mbr.inc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
;; File: mbr.inc
|
||||||
|
|
||||||
|
|
||||||
|
struc Partition
|
||||||
|
{
|
||||||
|
.status db ?
|
||||||
|
.chs_start db 3 dup(?)
|
||||||
|
.type db ?
|
||||||
|
.chs_last db 3 dup(?)
|
||||||
|
.lba dd ?
|
||||||
|
.sectors dd ?
|
||||||
|
}
|
||||||
|
defn Partition
|
||||||
|
|
||||||
|
|
|
@ -50,3 +50,4 @@ Section: UEFI (IA32)
|
||||||
> | BOOTIA32.EFI |----->| vmstupid.sys |
|
> | BOOTIA32.EFI |----->| vmstupid.sys |
|
||||||
> +--------------+ +--------------+
|
> +--------------+ +--------------+
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ TARGET = stpdldr.sys
|
||||||
|
|
||||||
LOADER_SRCS = loader.asm \
|
LOADER_SRCS = loader.asm \
|
||||||
../common/const.inc \
|
../common/const.inc \
|
||||||
|
video.inc \
|
||||||
|
memory.inc \
|
||||||
|
logger.inc \
|
||||||
a20.inc \
|
a20.inc \
|
||||||
multiboot.inc
|
multiboot.inc
|
||||||
|
|
||||||
|
|
|
@ -27,20 +27,41 @@ _start:
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
|
mov [drive_number], dl
|
||||||
|
|
||||||
mov si, msg_stage2
|
mov si, msg_stage2
|
||||||
call bios_print
|
call bios_log
|
||||||
|
|
||||||
; enable A20 line
|
; enable A20 line
|
||||||
call a20_enable
|
call a20_enable
|
||||||
jc .error_a20
|
jc .error_a20
|
||||||
|
|
||||||
|
; check drive type
|
||||||
|
; dl <= 0x7F == floppy
|
||||||
|
; dl >= 0x80 == hard drive
|
||||||
|
; dl == 0xE0 ~= CD/DVD
|
||||||
|
; dl <= 0xFF == hard drive
|
||||||
|
mov dl, [drive_number]
|
||||||
|
cmp dl, 0x7F
|
||||||
|
; skip disk extension check
|
||||||
|
jle @f
|
||||||
|
|
||||||
|
; check disk extensions
|
||||||
|
mov ah, 0x41
|
||||||
|
mov bx, 0x55AA
|
||||||
|
int 0x13
|
||||||
|
jc @f
|
||||||
|
mov [drive_lba], 1
|
||||||
|
@@:
|
||||||
|
; detect filesystem (FAT12/16 or StpdFS)
|
||||||
|
; load kernel from filesystem
|
||||||
|
|
||||||
; fetch memory map from bios
|
; fetch memory map from bios
|
||||||
call memory_get_map
|
call memory_get_map
|
||||||
jc .error_memory
|
jc .error_memory
|
||||||
|
|
||||||
; video information
|
; video information
|
||||||
call video_setup
|
call video_setup
|
||||||
xchg bx, bx
|
|
||||||
|
|
||||||
; load GDT and enter Protected-Mode
|
; load GDT and enter Protected-Mode
|
||||||
lgdt [gdt_ptr]
|
lgdt [gdt_ptr]
|
||||||
|
@ -65,21 +86,26 @@ _start:
|
||||||
.error_a20:
|
.error_a20:
|
||||||
mov si, msg_error_a20
|
mov si, msg_error_a20
|
||||||
.error:
|
.error:
|
||||||
call bios_print
|
call bios_log
|
||||||
@@:
|
@@:
|
||||||
hlt
|
hlt
|
||||||
jmp @b
|
jmp @b
|
||||||
|
|
||||||
include 'a20.inc'
|
include 'a20.inc'
|
||||||
include '../common/bios.inc'
|
include '../common/bios.inc'
|
||||||
|
include 'logger.inc'
|
||||||
include 'memory.inc'
|
include 'memory.inc'
|
||||||
include 'video.inc'
|
include 'video.inc'
|
||||||
include 'gdt.inc'
|
include 'gdt.inc'
|
||||||
|
|
||||||
msg_stage2 db "StupidOS Loader", CR, LF, 0
|
drive_number rb 1
|
||||||
|
drive_lba db 0
|
||||||
|
|
||||||
|
msg_stage2 db "StupidOS Loader", 0
|
||||||
kernel_fat12_file db "VMSTUPIDSYS", 0
|
kernel_fat12_file db "VMSTUPIDSYS", 0
|
||||||
msg_error_a20 db "ERROR: can't enable a20 line", CR, LF, 0
|
config_fat12_file db "BOOT INI", 0
|
||||||
msg_error_memory db "ERROR: can't detect available memory", CR, LF, 0
|
msg_error_a20 db "ERROR: can't enable a20 line", 0
|
||||||
|
msg_error_memory db "ERROR: can't detect available memory", 0
|
||||||
|
|
||||||
use32
|
use32
|
||||||
; =========================================================================
|
; =========================================================================
|
||||||
|
@ -101,6 +127,10 @@ common32:
|
||||||
; identity map first 1MB
|
; identity map first 1MB
|
||||||
; map kernel to 0xC0000000
|
; map kernel to 0xC0000000
|
||||||
|
|
||||||
|
push STPDBOOT_MAGIC
|
||||||
|
|
||||||
|
mov eax, 0xC0000000
|
||||||
|
jmp eax
|
||||||
hang:
|
hang:
|
||||||
hlt
|
hlt
|
||||||
jmp $
|
jmp $
|
||||||
|
|
54
boot/loader/logger.inc
Normal file
54
boot/loader/logger.inc
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
bios_log_time:
|
||||||
|
clc
|
||||||
|
mov ah, 0x02
|
||||||
|
int 0x1A
|
||||||
|
|
||||||
|
mov al, ch
|
||||||
|
aam
|
||||||
|
add ah, 0x30
|
||||||
|
add al, 0x30
|
||||||
|
mov [time + 1], ah
|
||||||
|
mov [time + 2], al
|
||||||
|
|
||||||
|
mov al, cl
|
||||||
|
aam
|
||||||
|
add ah, 0x30
|
||||||
|
add al, 0x30
|
||||||
|
mov [time + 4], ah
|
||||||
|
mov [time + 5], al
|
||||||
|
|
||||||
|
mov al, dh
|
||||||
|
aam
|
||||||
|
add ah, 0x30
|
||||||
|
add al, 0x30
|
||||||
|
mov [time + 7], ah
|
||||||
|
mov [time + 8], al
|
||||||
|
|
||||||
|
mov si, time
|
||||||
|
call bios_print
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
bios_log_hex:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Function: bios_log
|
||||||
|
;;
|
||||||
|
;; Parameters:
|
||||||
|
;; SI - string to print
|
||||||
|
;; [STACK] - variadic arguments
|
||||||
|
;;
|
||||||
|
bios_log:
|
||||||
|
push si
|
||||||
|
call bios_log_time
|
||||||
|
pop si
|
||||||
|
|
||||||
|
call bios_print
|
||||||
|
|
||||||
|
|
||||||
|
mov si, endline
|
||||||
|
call bios_print
|
||||||
|
ret
|
||||||
|
|
||||||
|
time db '[00:00.00] ', 0
|
||||||
|
endline db CR, LF, 0
|
|
@ -65,6 +65,9 @@ memory_e820_get_map:
|
||||||
;; BX - Extended 2
|
;; BX - Extended 2
|
||||||
;; CX - Configured 1
|
;; CX - Configured 1
|
||||||
;; DX - Configured 2
|
;; DX - Configured 2
|
||||||
|
memory_get_for_large_conf:
|
||||||
|
mov ax, 0xE801
|
||||||
|
int 0x15
|
||||||
|
|
||||||
;; Function: memory_get_extended_memory_size
|
;; Function: memory_get_extended_memory_size
|
||||||
;;
|
;;
|
||||||
|
@ -75,4 +78,5 @@ memory_e820_get_map:
|
||||||
;; CF - Non-Carry - indicates no error
|
;; CF - Non-Carry - indicates no error
|
||||||
;; AX - Number of contiguous KB above 1MB
|
;; AX - Number of contiguous KB above 1MB
|
||||||
memory_get_map:
|
memory_get_map:
|
||||||
|
clc
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -82,6 +82,7 @@ struc MultibootData
|
||||||
.fb_type db ?
|
.fb_type db ?
|
||||||
.fb_misc dw 3 dup ?
|
.fb_misc dw 3 dup ?
|
||||||
}
|
}
|
||||||
|
defn MultibootData
|
||||||
|
|
||||||
MULTIBOOT_DATA_MEM = 0x0001
|
MULTIBOOT_DATA_MEM = 0x0001
|
||||||
MULTIBOOT_DATA_BOOTDEV = 0x0002
|
MULTIBOOT_DATA_BOOTDEV = 0x0002
|
||||||
|
@ -100,6 +101,7 @@ struc MultibootMMap
|
||||||
.length dq ?
|
.length dq ?
|
||||||
.type dd ?
|
.type dd ?
|
||||||
}
|
}
|
||||||
|
defn MultibootMMap
|
||||||
|
|
||||||
MULTIBOOT_MEMORY_AVAILABLE = 0x1
|
MULTIBOOT_MEMORY_AVAILABLE = 0x1
|
||||||
MULTIBOOT_MEMORY_RESERVED = 0x2
|
MULTIBOOT_MEMORY_RESERVED = 0x2
|
||||||
|
@ -114,3 +116,4 @@ struc MultibootModule
|
||||||
.cmdline dd ?
|
.cmdline dd ?
|
||||||
.pad dd ?
|
.pad dd ?
|
||||||
}
|
}
|
||||||
|
defn MultibootModule
|
||||||
|
|
|
@ -14,6 +14,7 @@ struc VesaInfo
|
||||||
.Reserved db 222 dup(?)
|
.Reserved db 222 dup(?)
|
||||||
.OEMData db 256 dup(?)
|
.OEMData db 256 dup(?)
|
||||||
}
|
}
|
||||||
|
defn VesaInfo
|
||||||
|
|
||||||
struc VesaModeInfo
|
struc VesaModeInfo
|
||||||
{
|
{
|
||||||
|
@ -59,4 +60,29 @@ struc VesaModeInfo
|
||||||
defn VesaModeInfo
|
defn VesaModeInfo
|
||||||
|
|
||||||
video_setup:
|
video_setup:
|
||||||
|
clc
|
||||||
|
mov di, [vesa_block_buffer]
|
||||||
|
mov ax, 0x4F00
|
||||||
|
int 0x10
|
||||||
|
cmp ax, 0x004F
|
||||||
|
jne .err
|
||||||
|
|
||||||
|
push word [vesa_block_buffer + VesaInfo.VideoModesSegment]
|
||||||
|
pop es
|
||||||
|
mov di, vesa_info_block_buffer
|
||||||
|
mov bx, [vesa_block_buffer + VesaInfo.VideoModesOffset]
|
||||||
|
mov cx, [bx]
|
||||||
|
cmp cx, 0xFFFF
|
||||||
|
je .err
|
||||||
|
|
||||||
|
mov ax, 0x4F01
|
||||||
|
int 0x10
|
||||||
|
cmp ax, 0x004F
|
||||||
|
jne .err
|
||||||
ret
|
ret
|
||||||
|
.err:
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
|
||||||
|
vesa_block_buffer VesaInfo
|
||||||
|
vesa_info_block_buffer VesaModeInfo
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# define ECHFS_H 1
|
# define ECHFS_H 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint8_t jmp[4];
|
||||||
|
uint8_t signature[8];
|
||||||
|
|
||||||
} EchFSIdentityTable;
|
} EchFSIdentityTable;
|
||||||
|
|
|
@ -8,7 +8,15 @@
|
||||||
|
|
||||||
include 'mm/mm.inc'
|
include 'mm/mm.inc'
|
||||||
|
|
||||||
|
;; Function: kmain
|
||||||
|
;;
|
||||||
|
;; Parameters:
|
||||||
|
;;
|
||||||
|
;; EAX - Boot Magic
|
||||||
|
;; EBX - Boot structure address
|
||||||
|
;;
|
||||||
kmain:
|
kmain:
|
||||||
|
; TODO: interupt, vmm
|
||||||
nop
|
nop
|
||||||
|
|
||||||
_edata:
|
_edata:
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
free_block_head dd 0x0
|
free_block_head dd 0x0
|
||||||
|
|
||||||
mm_init:
|
mm_init:
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
SUBDIRS = csu crypto lzp
|
SUBDIRS = csu crypto lzp c
|
||||||
|
|
||||||
TOPGOALS = all clean install
|
TOPGOALS = all clean install
|
||||||
|
|
||||||
|
|
20
lib/c/Makefile
Normal file
20
lib/c/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
TARGET = libc.a
|
||||||
|
OBJS = ctype.o
|
||||||
|
INCS = stddef.h time.h ctype.h
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
%.o: %.asm
|
||||||
|
$(AS) $< $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(TARGET) $(OBJS)
|
||||||
|
|
||||||
|
install: $(TARGET)
|
||||||
|
@ mkdir -p $(DESTDIR)$(LIBDIR)
|
||||||
|
install $(TARGET) $(DESTDIR)$(LIBDIR)
|
||||||
|
@ mkdir -p $(DESTDIR)$(INCDIR)
|
||||||
|
install $(INCS) $(DESTDIR)$(INCDIR)
|
34
lib/c/ctype.asm
Normal file
34
lib/c/ctype.asm
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
format COFF
|
||||||
|
use32
|
||||||
|
|
||||||
|
public isdigit
|
||||||
|
|
||||||
|
section '.code' code
|
||||||
|
|
||||||
|
;; Function: isdigit
|
||||||
|
;;
|
||||||
|
;; Parameters:
|
||||||
|
;;
|
||||||
|
;; [esp+8] - character
|
||||||
|
;;
|
||||||
|
;; Returns:
|
||||||
|
;;
|
||||||
|
;; eax - 1 if digit otherwhise 0
|
||||||
|
;;
|
||||||
|
isdigit:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
mov al, '0'
|
||||||
|
mov cl, byte [esp+8]
|
||||||
|
cmp al, cl
|
||||||
|
jb @f
|
||||||
|
mov al, '9'
|
||||||
|
cmp al, cl
|
||||||
|
jg @f
|
||||||
|
mov eax, 1
|
||||||
|
jmp .end
|
||||||
|
@@:
|
||||||
|
xor eax, eax
|
||||||
|
.end:
|
||||||
|
leave
|
||||||
|
ret
|
7
lib/c/ctype.h
Normal file
7
lib/c/ctype.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef CTYPE_H
|
||||||
|
# define CTYPE_H 1
|
||||||
|
|
||||||
|
int isalnum(int c);
|
||||||
|
int isdigit(int c);
|
||||||
|
|
||||||
|
#endif /* !CTYPE_H */
|
6
lib/c/stddef.h
Normal file
6
lib/c/stddef.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef STDDEF_H
|
||||||
|
# define STDDEF_H 1
|
||||||
|
|
||||||
|
typedef unsigned int size_t;
|
||||||
|
|
||||||
|
#endif /* !STDDEF_H */
|
31
lib/c/time.h
Normal file
31
lib/c/time.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef TIME_H
|
||||||
|
# define TIME_H 1
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
/* POSIX define CLOCKS_PER_SEC as on milion */
|
||||||
|
# define CLOCKS_PER_SEC 1000000
|
||||||
|
|
||||||
|
typedef int64_t time_t;
|
||||||
|
typedef uint64_t clock_t;
|
||||||
|
|
||||||
|
struct tm {
|
||||||
|
int tm_sec;
|
||||||
|
int tm_min;
|
||||||
|
int tm_hour;
|
||||||
|
int tm_mday;
|
||||||
|
int tm_mon;
|
||||||
|
int tm_year;
|
||||||
|
int tm_wday;
|
||||||
|
int tm_yday;
|
||||||
|
int tm_isdst;
|
||||||
|
};
|
||||||
|
|
||||||
|
double difftime(time_t time_end, time_t time_beg);
|
||||||
|
time_t time(time_t *arg);
|
||||||
|
clock_t clock(void);
|
||||||
|
char *asctime(const struct tm *time); /* fuck modern C */
|
||||||
|
char *ctime(const time_t *timer);
|
||||||
|
size_t strftime(char *str, size_t count, const char *format, const struct tm *tp);
|
||||||
|
|
||||||
|
#endif /* !TIME_H */
|
175
sbin/mkfs.stpd/main.c
Normal file
175
sbin/mkfs.stpd/main.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define MAGIC 0x44505453
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 512
|
||||||
|
|
||||||
|
struct superblock {
|
||||||
|
uint32_t magic;
|
||||||
|
uint32_t isize;
|
||||||
|
uint32_t fsize;
|
||||||
|
uint32_t free[100];
|
||||||
|
uint8_t nfree;
|
||||||
|
uint8_t flock;
|
||||||
|
uint8_t ilock;
|
||||||
|
uint8_t fmod;
|
||||||
|
uint32_t time[2];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct inode {
|
||||||
|
uint16_t mode;
|
||||||
|
uint8_t nlink;
|
||||||
|
uint8_t uid;
|
||||||
|
uint8_t gid;
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t addr[8];
|
||||||
|
uint32_t actime[2];
|
||||||
|
uint32_t modtime[2];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define INODE_SIZE sizeof(struct inode)
|
||||||
|
|
||||||
|
struct file {
|
||||||
|
unsigned short inode;
|
||||||
|
char filename[14];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *prg_name = NULL;
|
||||||
|
static int verbose = 0;
|
||||||
|
static const char *device = NULL;
|
||||||
|
static int devfd = 0;
|
||||||
|
static off_t device_size = 0;
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_sector(size_t secnum, const uint8_t *data, size_t buff_size)
|
||||||
|
{
|
||||||
|
uint8_t buffer[BLOCK_SIZE];
|
||||||
|
|
||||||
|
if (lseek(devfd, secnum * BLOCK_SIZE, SEEK_SET) != (secnum * BLOCK_SIZE))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: %s\n", device, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
|
memcpy(buffer, data, buff_size);
|
||||||
|
|
||||||
|
if (write(devfd, buffer, BLOCK_SIZE) != BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: x %s\n", device, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(int retcode)
|
||||||
|
{
|
||||||
|
if (retcode == EXIT_FAILURE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Try '%s -h' for more informations.\n", prg_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Usage: %s [-hVv] disk\n", prg_name);
|
||||||
|
printf("\t-h\tdisplay this help and exit\n");
|
||||||
|
printf("\t-V\toutput version information.\n");
|
||||||
|
printf("\nReport bugs to <%s>\n", MK_BUGREPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(retcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
version(void)
|
||||||
|
{
|
||||||
|
printf("%s commit %s\n", prg_name, MK_COMMIT);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct stat inf;
|
||||||
|
int idx;
|
||||||
|
uint8_t buffer[BLOCK_SIZE];
|
||||||
|
struct superblock sb;
|
||||||
|
|
||||||
|
prg_name = argv[0];
|
||||||
|
|
||||||
|
while ((argc > 1) && (argv[1][0]) == '-')
|
||||||
|
{
|
||||||
|
switch (argv[1][1])
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
version();
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose=1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc <= 1) usage(EXIT_FAILURE);
|
||||||
|
|
||||||
|
device = argv[1];
|
||||||
|
|
||||||
|
if (stat(device, &inf) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: %s\n", device, strerror(errno));
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_size = inf.st_size;
|
||||||
|
|
||||||
|
if (verbose) printf("Device size: %ld (%ld blocks)\n", device_size, device_size/BLOCK_SIZE);
|
||||||
|
|
||||||
|
/*if (device_size/BLOCK_SIZE > 0x7fff)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: File too large\n", device);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
devfd = open(device, O_WRONLY);
|
||||||
|
if (devfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: %s\n", device, strerror(errno));
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
|
for (idx = 0; idx < device_size/BLOCK_SIZE; idx++)
|
||||||
|
{
|
||||||
|
write_sector(idx, buffer, BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
if (verbose) printf("Write %ld (%ld bytes)\n", device_size/BLOCK_SIZE, device_size);
|
||||||
|
|
||||||
|
memset(&sb, 0, sizeof(struct superblock));
|
||||||
|
|
||||||
|
sb.magic = MAGIC;
|
||||||
|
sb.fsize = device_size/BLOCK_SIZE;
|
||||||
|
|
||||||
|
write_sector(1, (uint8_t *)&sb, sizeof(struct superblock));
|
||||||
|
|
||||||
|
//sb.ninode = (device_size/BLOCK_SIZE) / 8;
|
||||||
|
|
||||||
|
printf("sizeof %lu %lu\n", sizeof(struct superblock), sizeof(struct inode));
|
||||||
|
|
||||||
|
close(devfd);
|
||||||
|
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
304
sbin/mkfs.stpd/v6.5
Normal file
304
sbin/mkfs.stpd/v6.5
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
|
||||||
|
V6/usr/man/man5/fs.5
|
||||||
|
Compare this file to the similar file:
|
||||||
|
|
||||||
|
Show the results in this format:
|
||||||
|
|
||||||
|
.TH "FILE SYSTEM" V 2/9/75
|
||||||
|
.SH NAME
|
||||||
|
fs \*- format of file system volume
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Every
|
||||||
|
file system storage volume
|
||||||
|
(e.g. RF disk, RK disk, RP disk, DECtape reel)
|
||||||
|
has a common format for certain vital information.
|
||||||
|
Every such volume is divided into a certain number
|
||||||
|
of 256 word (512 byte) blocks.
|
||||||
|
Block 0 is unused and is available to contain
|
||||||
|
a bootstrap program, pack label, or other information.
|
||||||
|
.s3
|
||||||
|
Block 1 is the
|
||||||
|
.IB "super block."
|
||||||
|
Starting from its first word, the format of a super-block is
|
||||||
|
.s3
|
||||||
|
.nf
|
||||||
|
struct {
|
||||||
|
int isize;
|
||||||
|
int fsize;
|
||||||
|
int nfree;
|
||||||
|
int free[100];
|
||||||
|
int ninode;
|
||||||
|
int inode[100];
|
||||||
|
char flock;
|
||||||
|
char ilock;
|
||||||
|
char fmod;
|
||||||
|
int time[2];
|
||||||
|
};
|
||||||
|
.s3
|
||||||
|
.fi
|
||||||
|
.IP Isize
|
||||||
|
is the number of blocks devoted to the i-list,
|
||||||
|
which starts just after the super-block, in block 2.
|
||||||
|
.IP Fsize
|
||||||
|
is the first block not potentially available for allocation
|
||||||
|
to a file.
|
||||||
|
These numbers are used by the system to
|
||||||
|
check for bad block numbers;
|
||||||
|
if an ``impossible'' block number is allocated from the free list
|
||||||
|
or is freed,
|
||||||
|
a diagnostic is written on the on-line console.
|
||||||
|
Moreover, the free array is cleared, so as to prevent further
|
||||||
|
allocation from a presumably corrupted free list.
|
||||||
|
.s3
|
||||||
|
The free list for each volume is maintained as
|
||||||
|
follows.
|
||||||
|
The
|
||||||
|
.IB free
|
||||||
|
array contains, in
|
||||||
|
.IB "free[1], ... , free[nfree\*-1],"
|
||||||
|
up to 99 numbers of free blocks.
|
||||||
|
.IB Free[0]
|
||||||
|
is the block number of the head
|
||||||
|
of a chain of blocks constituting the free list.
|
||||||
|
The first word in each free-chain block is the number
|
||||||
|
(up to 100) of free-block numbers listed in the
|
||||||
|
next 100 words of this chain member.
|
||||||
|
The first of these 100 blocks is the link to the
|
||||||
|
next member of the chain.
|
||||||
|
To allocate a block:
|
||||||
|
decrement
|
||||||
|
.IB nfree,
|
||||||
|
and the new block is
|
||||||
|
.IB free[nfree].
|
||||||
|
If the new block number is 0,
|
||||||
|
there are no blocks left, so give an error.
|
||||||
|
If
|
||||||
|
.IB nfree
|
||||||
|
became 0,
|
||||||
|
read in the block named by the new block number,
|
||||||
|
replace
|
||||||
|
.IB nfree
|
||||||
|
by its first word,
|
||||||
|
and copy the block numbers in the next 100 words into the
|
||||||
|
.IB free
|
||||||
|
array.
|
||||||
|
To free a block, check if
|
||||||
|
.IB nfree
|
||||||
|
is 100; if so,
|
||||||
|
copy
|
||||||
|
.IB nfree
|
||||||
|
and the
|
||||||
|
.IB free
|
||||||
|
array into it,
|
||||||
|
write it out, and set
|
||||||
|
.IB nfree
|
||||||
|
to 0.
|
||||||
|
In any event set
|
||||||
|
.IB free[nfree]
|
||||||
|
to the freed block's number and
|
||||||
|
increment
|
||||||
|
.IB nfree.
|
||||||
|
.s3
|
||||||
|
.IB Ninode
|
||||||
|
is the number of free i-numbers in the
|
||||||
|
.IB inode
|
||||||
|
array.
|
||||||
|
To allocate an i-node:
|
||||||
|
if
|
||||||
|
.IB ninode
|
||||||
|
is greater than 0,
|
||||||
|
decrement it and return
|
||||||
|
.IB inode[ninode].
|
||||||
|
If it was 0, read the i-list
|
||||||
|
and place the numbers of all free inodes
|
||||||
|
(up to 100) into the
|
||||||
|
.IB inode
|
||||||
|
array,
|
||||||
|
then try again.
|
||||||
|
To free an i-node,
|
||||||
|
provided
|
||||||
|
.IB ninode
|
||||||
|
is less than 100,
|
||||||
|
place its number into
|
||||||
|
.IB inode[ninode]
|
||||||
|
and increment
|
||||||
|
.IB ninode.
|
||||||
|
If
|
||||||
|
.IB ninode
|
||||||
|
is already 100, don't bother to enter the freed i-node into any table.
|
||||||
|
This list of i-nodes is only to speed
|
||||||
|
up the allocation process; the information
|
||||||
|
as to whether the inode is really free
|
||||||
|
or not is maintained in the inode itself.
|
||||||
|
.s3
|
||||||
|
.IB Flock
|
||||||
|
and
|
||||||
|
.IB ilock
|
||||||
|
are flags maintained in the core
|
||||||
|
copy of the file system
|
||||||
|
while it is mounted
|
||||||
|
and their values on disk are immaterial.
|
||||||
|
The value of
|
||||||
|
.IB fmod
|
||||||
|
on disk is likewise immaterial;
|
||||||
|
it is used as a flag to indicate that the super-block has
|
||||||
|
changed and should be copied to
|
||||||
|
the disk during the next periodic update of file
|
||||||
|
system information.
|
||||||
|
.s3
|
||||||
|
.IB Time
|
||||||
|
is the last time the super-block of the file system was changed,
|
||||||
|
and is a double-precision representation
|
||||||
|
of the number of seconds that have elapsed
|
||||||
|
since
|
||||||
|
0000 Jan. 1 1970 (GMT).
|
||||||
|
During a reboot, the
|
||||||
|
.IB time
|
||||||
|
of the super-block for the root file system
|
||||||
|
is used to set the system's idea of the time.
|
||||||
|
.s3
|
||||||
|
I-numbers begin at 1, and the storage for i-nodes
|
||||||
|
begins in block 2.
|
||||||
|
.tr |
|
||||||
|
Also, i-nodes are 32 bytes long, so 16 of them fit into a block.
|
||||||
|
Therefore, i-node
|
||||||
|
.IB i
|
||||||
|
is located in block (\fIi\fR|+|31)|/|16, and begins
|
||||||
|
32\u\fB.\fR\d((\fIi\fR|+|31)|(mod 16) bytes from its start.
|
||||||
|
I-node 1 is reserved for the root directory of the file
|
||||||
|
system, but no other i-number has a built-in
|
||||||
|
meaning.
|
||||||
|
Each i-node represents one file.
|
||||||
|
The format of an i-node is as follows.
|
||||||
|
.s3
|
||||||
|
.nf
|
||||||
|
.if t .ta .5i 1.i 2.5i
|
||||||
|
struct {
|
||||||
|
int flags; /* +0: see below */
|
||||||
|
char nlinks; /* +2: number of links to file */
|
||||||
|
char uid; /* +3: user ID of owner */
|
||||||
|
char gid; /* +4: group ID of owner */
|
||||||
|
char size0; /* +5: high byte of 24-bit size */
|
||||||
|
int size1; /* +6: low word of 24-bit size */
|
||||||
|
int addr[8]; /* +8: block numbers or device number */
|
||||||
|
int actime[2]; /* +24: time of last access */
|
||||||
|
int modtime[2]; /* +28: time of last modification */
|
||||||
|
};
|
||||||
|
.dt
|
||||||
|
.fi
|
||||||
|
.s3
|
||||||
|
The flags are as follows:
|
||||||
|
.s3
|
||||||
|
.lp +10 9
|
||||||
|
100000 i-node is allocated
|
||||||
|
.lp +10 9
|
||||||
|
060000 2-bit file type:
|
||||||
|
.lp +15 9
|
||||||
|
000000 plain file
|
||||||
|
.lp +15 9
|
||||||
|
040000 directory
|
||||||
|
.lp +15 9
|
||||||
|
020000 character-type special file
|
||||||
|
.lp +15 9
|
||||||
|
060000 block-type special file.
|
||||||
|
.lp +10 9
|
||||||
|
010000 large file
|
||||||
|
.lp +10 9
|
||||||
|
004000 set user-ID on execution
|
||||||
|
.lp +10 9
|
||||||
|
002000 set group-ID on execution
|
||||||
|
.lp +10 9
|
||||||
|
000400 read (owner)
|
||||||
|
.lp +10 9
|
||||||
|
000200 write (owner)
|
||||||
|
.lp +10 9
|
||||||
|
000100 execute (owner)
|
||||||
|
.lp +10 9
|
||||||
|
000070 read, write, execute (group)
|
||||||
|
.lp +10 9
|
||||||
|
000007 read, write, execute (others)
|
||||||
|
.s3
|
||||||
|
.i0
|
||||||
|
Special files are recognized by their flags
|
||||||
|
and not by i-number.
|
||||||
|
A block-type special file is basically one which
|
||||||
|
can potentially be mounted as a file system;
|
||||||
|
a character-type special file cannot, though it is
|
||||||
|
not necessarily character-oriented.
|
||||||
|
For special files the high byte of the first address word
|
||||||
|
specifies the type of device; the low byte specifies
|
||||||
|
one of several devices of
|
||||||
|
that type.
|
||||||
|
The device type numbers
|
||||||
|
of block and character special files overlap.
|
||||||
|
.s3
|
||||||
|
The address words of ordinary files and directories
|
||||||
|
contain the numbers of the blocks in the
|
||||||
|
file (if it is small)
|
||||||
|
or the numbers of indirect blocks (if the file
|
||||||
|
is large).
|
||||||
|
Byte number
|
||||||
|
.IB n
|
||||||
|
of a file is accessed as follows.
|
||||||
|
.IB N
|
||||||
|
is divided by 512 to find its logical block number
|
||||||
|
(say
|
||||||
|
.IB b
|
||||||
|
)
|
||||||
|
in the file.
|
||||||
|
If the file is small (flag 010000 is 0),
|
||||||
|
then
|
||||||
|
.IB b
|
||||||
|
must be less than 8, and the physical
|
||||||
|
block number is
|
||||||
|
.IB addr[b].
|
||||||
|
.s3
|
||||||
|
If the file is large,
|
||||||
|
.IB b
|
||||||
|
is divided by 256 to yield
|
||||||
|
.IB i.
|
||||||
|
If
|
||||||
|
.IB i
|
||||||
|
is less than 7, then
|
||||||
|
.IB addr[i]
|
||||||
|
is the physical block number of
|
||||||
|
the indirect block.
|
||||||
|
The remainder from the division
|
||||||
|
yields the word in the indirect block
|
||||||
|
which contains the number of the block for
|
||||||
|
the sought-for byte.
|
||||||
|
.s3
|
||||||
|
If
|
||||||
|
.IB i
|
||||||
|
is equal to 7,
|
||||||
|
then the file has become extra-large (huge),
|
||||||
|
and
|
||||||
|
.IB addr[7]
|
||||||
|
is the address of a first indirect block.
|
||||||
|
Each word in this block
|
||||||
|
is the number of a second-level indirect block;
|
||||||
|
each word in the second-level indirect blocks points to a data block.
|
||||||
|
Notice that extra-large files are not marked by any mode
|
||||||
|
bit, but only by having
|
||||||
|
.IB addr[7]
|
||||||
|
non-zero;
|
||||||
|
and that although this scheme allows for more than
|
||||||
|
256\*X256\*X512 = 33,554,432 bytes per file,
|
||||||
|
the length of files is stored in 24 bits
|
||||||
|
so in practice a file can be at most
|
||||||
|
16,777,216 bytes long.
|
||||||
|
.s3
|
||||||
|
For block
|
||||||
|
.IB b
|
||||||
|
in a file to exist,
|
||||||
|
it
|
||||||
|
is not necessary that all blocks less than
|
||||||
|
.IB b
|
||||||
|
exist.
|
||||||
|
A zero block number either in the address words of
|
||||||
|
the i-node or in an indirect block indicates that the
|
||||||
|
corresponding block has never been allocated.
|
||||||
|
Such a missing block reads as if it contained all zero words.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
icheck, dcheck (VIII)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
RM = rm -f
|
RM = rm -f
|
||||||
|
|
||||||
TARGET = fat$(EXEXT) coff-ld$(EXEXT) parted$(EXEXT)
|
TARGET = fat$(EXEXT) coff-ld$(EXEXT) parted$(EXEXT) mkfs.stpd$(EXEXT)
|
||||||
|
|
||||||
CFLAGS = -DMK_COMMIT="$(MK_COMMIT)" -DMK_BUGREPORT="$(MK_BUGREPORT)" -I../include
|
CFLAGS = -DMK_COMMIT="$(MK_COMMIT)" -DMK_BUGREPORT="$(MK_BUGREPORT)" -I../include
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
@ -18,6 +18,9 @@ coff-ld$(EXEXT): coff-ld.c
|
||||||
parted$(EXEXT): ../sbin/parted/main.c
|
parted$(EXEXT): ../sbin/parted/main.c
|
||||||
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
|
mkfs.stpd$(EXEXT): ../sbin/mkfs.stpd/main.c
|
||||||
|
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: $(TARGET)
|
install: $(TARGET)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue