From fb51cf602a5d377275ba601ba09241f412d2f0d1 Mon Sep 17 00:00:00 2001 From: d0p1 Date: Sun, 28 Apr 2024 08:41:36 +0200 Subject: [PATCH] feat(loader): logger print time --- LICENSE | 2 +- boot/bootsect/floppy.asm | 2 + boot/bootsect/mbr.asm | 57 +++- boot/common/const.inc | 3 + boot/common/mbr.inc | 15 + boot/intro.txt | 1 + boot/loader/Makefile | 3 + boot/loader/loader.asm | 42 ++- boot/loader/logger.inc | 54 ++++ boot/loader/memory.inc | 4 + boot/loader/multiboot.inc | 3 + boot/loader/video.inc | 26 ++ .../fs/fat12.h => external/binutils/Makefile | 0 include/fs/{echfs.h => fat16.h} | 2 + kernel/kernel.asm | 8 + kernel/mm/mm.inc | 4 +- lib/Makefile | 2 +- lib/c/Makefile | 20 ++ lib/c/ctype.asm | 34 ++ lib/c/ctype.h | 7 + lib/c/stddef.h | 6 + lib/c/time.h | 31 ++ sbin/mkfs.stpd/main.c | 175 ++++++++++ sbin/mkfs.stpd/v6.5 | 304 ++++++++++++++++++ tools/Makefile | 5 +- 25 files changed, 796 insertions(+), 14 deletions(-) create mode 100644 boot/common/mbr.inc create mode 100644 boot/loader/logger.inc rename include/fs/fat12.h => external/binutils/Makefile (100%) rename include/fs/{echfs.h => fat16.h} (71%) create mode 100644 lib/c/Makefile create mode 100644 lib/c/ctype.asm create mode 100644 lib/c/ctype.h create mode 100644 lib/c/stddef.h create mode 100644 lib/c/time.h create mode 100644 sbin/mkfs.stpd/main.c create mode 100644 sbin/mkfs.stpd/v6.5 diff --git a/LICENSE b/LICENSE index fd4bae7..af789a0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020, d0p1 +Copyright (c) 2024, d0p1 All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/boot/bootsect/floppy.asm b/boot/bootsect/floppy.asm index 780c47f..04527ba 100644 --- a/boot/bootsect/floppy.asm +++ b/boot/bootsect/floppy.asm @@ -93,6 +93,8 @@ _start: xor bx, bx call fat_load_binary + mov dl, [drive_number] + jmp 0x0:LOADER_BASE .error_not_found: diff --git a/boot/bootsect/mbr.asm b/boot/bootsect/mbr.asm index 956d22e..8a91ebe 100644 --- a/boot/bootsect/mbr.asm +++ b/boot/bootsect/mbr.asm @@ -3,6 +3,8 @@ include '../common/const.inc' include '../common/macro.inc' + include '../common/bios.inc' + include '../common/mbr.inc' org MBR_BASE cli @@ -19,9 +21,60 @@ rep movsw jmp 0x0: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' ; partition table PT1 db 16 dup(0) diff --git a/boot/common/const.inc b/boot/common/const.inc index 2faf3e2..69f2b25 100644 --- a/boot/common/const.inc +++ b/boot/common/const.inc @@ -10,6 +10,9 @@ DISK_BUFFER = 0x8000 KERNEL_PRELOAD = 0xF000 STACK_TOP = 0x7000 +; ---------- Magic ------------ +STPDBOOT_MAGIC = 0x53545044 + ; ---------- Video ------------ VIDEO_WIDTH = 1024 VIDEO_HEIGHT = 768 diff --git a/boot/common/mbr.inc b/boot/common/mbr.inc new file mode 100644 index 0000000..1c4e01d --- /dev/null +++ b/boot/common/mbr.inc @@ -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 + + diff --git a/boot/intro.txt b/boot/intro.txt index b3cba46..5643756 100644 --- a/boot/intro.txt +++ b/boot/intro.txt @@ -50,3 +50,4 @@ Section: UEFI (IA32) > | BOOTIA32.EFI |----->| vmstupid.sys | > +--------------+ +--------------+ > + diff --git a/boot/loader/Makefile b/boot/loader/Makefile index 379aba2..1874150 100644 --- a/boot/loader/Makefile +++ b/boot/loader/Makefile @@ -2,6 +2,9 @@ TARGET = stpdldr.sys LOADER_SRCS = loader.asm \ ../common/const.inc \ + video.inc \ + memory.inc \ + logger.inc \ a20.inc \ multiboot.inc diff --git a/boot/loader/loader.asm b/boot/loader/loader.asm index 056bc88..c679b93 100644 --- a/boot/loader/loader.asm +++ b/boot/loader/loader.asm @@ -27,20 +27,41 @@ _start: push cs pop ds + mov [drive_number], dl + mov si, msg_stage2 - call bios_print + call bios_log ; enable A20 line call a20_enable 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 call memory_get_map jc .error_memory ; video information call video_setup - xchg bx, bx ; load GDT and enter Protected-Mode lgdt [gdt_ptr] @@ -65,21 +86,26 @@ _start: .error_a20: mov si, msg_error_a20 .error: - call bios_print + call bios_log @@: hlt jmp @b include 'a20.inc' include '../common/bios.inc' + include 'logger.inc' include 'memory.inc' include 'video.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 -msg_error_a20 db "ERROR: can't enable a20 line", CR, LF, 0 -msg_error_memory db "ERROR: can't detect available memory", CR, LF, 0 +config_fat12_file db "BOOT INI", 0 +msg_error_a20 db "ERROR: can't enable a20 line", 0 +msg_error_memory db "ERROR: can't detect available memory", 0 use32 ; ========================================================================= @@ -101,6 +127,10 @@ common32: ; identity map first 1MB ; map kernel to 0xC0000000 + push STPDBOOT_MAGIC + + mov eax, 0xC0000000 + jmp eax hang: hlt jmp $ diff --git a/boot/loader/logger.inc b/boot/loader/logger.inc new file mode 100644 index 0000000..9e194aa --- /dev/null +++ b/boot/loader/logger.inc @@ -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 diff --git a/boot/loader/memory.inc b/boot/loader/memory.inc index cedd087..4b96300 100644 --- a/boot/loader/memory.inc +++ b/boot/loader/memory.inc @@ -65,6 +65,9 @@ memory_e820_get_map: ;; BX - Extended 2 ;; CX - Configured 1 ;; DX - Configured 2 +memory_get_for_large_conf: + mov ax, 0xE801 + int 0x15 ;; Function: memory_get_extended_memory_size ;; @@ -75,4 +78,5 @@ memory_e820_get_map: ;; CF - Non-Carry - indicates no error ;; AX - Number of contiguous KB above 1MB memory_get_map: + clc ret diff --git a/boot/loader/multiboot.inc b/boot/loader/multiboot.inc index aadbcaf..cec1cd0 100644 --- a/boot/loader/multiboot.inc +++ b/boot/loader/multiboot.inc @@ -82,6 +82,7 @@ struc MultibootData .fb_type db ? .fb_misc dw 3 dup ? } +defn MultibootData MULTIBOOT_DATA_MEM = 0x0001 MULTIBOOT_DATA_BOOTDEV = 0x0002 @@ -100,6 +101,7 @@ struc MultibootMMap .length dq ? .type dd ? } +defn MultibootMMap MULTIBOOT_MEMORY_AVAILABLE = 0x1 MULTIBOOT_MEMORY_RESERVED = 0x2 @@ -114,3 +116,4 @@ struc MultibootModule .cmdline dd ? .pad dd ? } +defn MultibootModule diff --git a/boot/loader/video.inc b/boot/loader/video.inc index 35c2aa8..cbf007c 100644 --- a/boot/loader/video.inc +++ b/boot/loader/video.inc @@ -14,6 +14,7 @@ struc VesaInfo .Reserved db 222 dup(?) .OEMData db 256 dup(?) } +defn VesaInfo struc VesaModeInfo { @@ -59,4 +60,29 @@ struc VesaModeInfo defn VesaModeInfo 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 +.err: + stc + ret + +vesa_block_buffer VesaInfo +vesa_info_block_buffer VesaModeInfo diff --git a/include/fs/fat12.h b/external/binutils/Makefile similarity index 100% rename from include/fs/fat12.h rename to external/binutils/Makefile diff --git a/include/fs/echfs.h b/include/fs/fat16.h similarity index 71% rename from include/fs/echfs.h rename to include/fs/fat16.h index b0c2337..49e2ca3 100644 --- a/include/fs/echfs.h +++ b/include/fs/fat16.h @@ -2,6 +2,8 @@ # define ECHFS_H 1 typedef struct { + uint8_t jmp[4]; + uint8_t signature[8]; } EchFSIdentityTable; diff --git a/kernel/kernel.asm b/kernel/kernel.asm index b10955b..e8e7311 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -8,7 +8,15 @@ include 'mm/mm.inc' + ;; Function: kmain + ;; + ;; Parameters: + ;; + ;; EAX - Boot Magic + ;; EBX - Boot structure address + ;; kmain: + ; TODO: interupt, vmm nop _edata: diff --git a/kernel/mm/mm.inc b/kernel/mm/mm.inc index 8cc72e4..8f58973 100644 --- a/kernel/mm/mm.inc +++ b/kernel/mm/mm.inc @@ -1,6 +1,4 @@ free_block_head dd 0x0 mm_init: - - ret - \ No newline at end of file + ret diff --git a/lib/Makefile b/lib/Makefile index fdfc8f0..32637f0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = csu crypto lzp +SUBDIRS = csu crypto lzp c TOPGOALS = all clean install diff --git a/lib/c/Makefile b/lib/c/Makefile new file mode 100644 index 0000000..c3f46b4 --- /dev/null +++ b/lib/c/Makefile @@ -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) diff --git a/lib/c/ctype.asm b/lib/c/ctype.asm new file mode 100644 index 0000000..ec00691 --- /dev/null +++ b/lib/c/ctype.asm @@ -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 diff --git a/lib/c/ctype.h b/lib/c/ctype.h new file mode 100644 index 0000000..1e57aaa --- /dev/null +++ b/lib/c/ctype.h @@ -0,0 +1,7 @@ +#ifndef CTYPE_H +# define CTYPE_H 1 + +int isalnum(int c); +int isdigit(int c); + +#endif /* !CTYPE_H */ diff --git a/lib/c/stddef.h b/lib/c/stddef.h new file mode 100644 index 0000000..0841fad --- /dev/null +++ b/lib/c/stddef.h @@ -0,0 +1,6 @@ +#ifndef STDDEF_H +# define STDDEF_H 1 + +typedef unsigned int size_t; + +#endif /* !STDDEF_H */ diff --git a/lib/c/time.h b/lib/c/time.h new file mode 100644 index 0000000..d1ddbf4 --- /dev/null +++ b/lib/c/time.h @@ -0,0 +1,31 @@ +#ifndef TIME_H +# define TIME_H 1 + +# include + +/* 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 */ diff --git a/sbin/mkfs.stpd/main.c b/sbin/mkfs.stpd/main.c new file mode 100644 index 0000000..979c757 --- /dev/null +++ b/sbin/mkfs.stpd/main.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/sbin/mkfs.stpd/v6.5 b/sbin/mkfs.stpd/v6.5 new file mode 100644 index 0000000..850c703 --- /dev/null +++ b/sbin/mkfs.stpd/v6.5 @@ -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) + diff --git a/tools/Makefile b/tools/Makefile index 9a3c492..986e2aa 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,7 +1,7 @@ CC = gcc 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 LDFLAGS = @@ -18,6 +18,9 @@ coff-ld$(EXEXT): coff-ld.c parted$(EXEXT): ../sbin/parted/main.c $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) +mkfs.stpd$(EXEXT): ../sbin/mkfs.stpd/main.c + $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) + .PHONY: install install: $(TARGET)