commit: 87e9d7db9d22b400d1c05247254ac39ee2577e80
parent 26552a928f3bc10b8bfeb2c7ac1daf801ea15b38
Author: Andrius Štikonas <andrius@stikonas.eu>
Date: Sun, 21 May 2023 01:26:04 +0100
Merge pull request #295 from rick-masters/kernel-bootstrap-phase2-v1
Kernel bootstrap phase2 v1
Diffstat:
24 files changed, 3208 insertions(+), 3059 deletions(-)
diff --git a/kernel-bootstrap/builder-hex0-x86-stage2.hex0 b/kernel-bootstrap/builder-hex0-x86-stage2.hex0
@@ -0,0 +1,2442 @@
+# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
+# SPDX-License-Identifier: MIT
+#
+# Builder-Hex0 is a small bootable machine image which has
+# the ability to compile hex0 code. It is also written in hex0
+# and so it can build itself if provided with its own source code.
+#
+# hex0 is a "language" for binary encoding in hexadecimal
+# with support for comments.
+
+# 16 bit Functions
+# ----------------
+# stage2_entry
+# console_putc_16
+# console_put_hex_16
+#
+# get_drive_geometry
+# next_sector
+# read_sectors_16
+# write_sectors_16
+#
+# [GDT data]
+# stage2_main
+
+# 32 bit Functions
+# ----------------
+# setup_interrupt_handlers
+# stub_interrupt_handler
+# enter_16bit_real
+# resume_32bit_mode
+#
+# console_putc
+# console_put_hex
+# console_puts
+# read_sectors
+# write_sectors
+#
+# syscall_interrupt_handler
+# handle_syscall_open
+# handle_syscall_close
+# absolute_path
+# find_file
+# fd_to_file_index
+# handle_syscall_read
+# handle_syscall_brk
+# handle_syscall_write
+# handle_syscall_fork
+# handle_syscall_execve
+# handle_syscall_chdir
+# handle_syscall_exit
+# handle_syscall_waitpid
+# handle_syscall_lseek
+# handle_syscall_access
+# handle_syscall_mkdir
+# handle_syscall_getcwd
+#
+# strcmp
+#
+# read
+# write
+# src
+# hex0
+# internalshell
+
+
+#------------------------------------------------------------
+# Memory:
+# 54000000 - BFFFFFFF files (~1812MB)
+# 30000000 - 53FFFFFF saved processes (~604MB)
+# 08048000 - 2FFFFFFF current running process (~670MB)
+# 01080000 - 08000000 32 bit stack (117MB)
+# 01000010 - 0107FFFF file descriptors (16 bytes each * 32K)
+# { unused, address, length, unused }
+# 01000000 - 0100000F stdin disk locator
+# { cylinder/sector (2 bytes), head (1 byte), unused byte,
+# offset (2 bytes), unused }
+# 201800 - FFFFFF file names 6..14335
+# 201400 - 2017FF file name 5
+# 201000 - 2013FF file name 4
+# 100000 - 200FF0 unused
+# 9FC00 - FFFFF BIOS
+# 40200 - 9FBFF scratch buffer
+# 40000 - 401FF stdin device buffer
+# 20000 - 3FFFF process descriptors ( 16 * 4096 bytes each)
+# offset len description
+# 0x000 0x004 process address
+# 0x004 0x004 brk pointer
+# 0x008 0x004 saved stack pointer (first process only)
+# 0x00C 0x004 saved stack pointer
+# 0x010 0x004 forked?
+# 0x014 0x004 saved brk pointer
+# 0x018 0x004 child exit code
+# 0x01C 0x004 address of saved process memory
+# 0x020 0x004 length of process memory
+# 0x024 0x004 address of saved process stack
+# 0x028 0x004 length of saved process stack
+# 0x02C 0x01C unused
+# 0x100 0x100 current directory
+# 0x200 x0E00 file descriptors 448 * 8 bytes each
+# { global_file_index, current_offset }
+# 10800 - 1FFFF unused
+# 10000 - 107FF interrupt table
+# A000 - A1FF sector read buffer - 16bit
+# 7C00 - 8600 code
+# 7B00 - 7BFF Saved 32 bit registers while in 16 bit mode
+# < 7B00 real mode stack
+#------------------------------------------------------------
+
+
+#------------------------------------------------------------
+#[7E00]
+#:stage2_entry
+# inputs:
+# dl: boot drive
+#
+# We cannot be sure the registers are initialized to zero so we
+# do that first. We far jump to stage2_main in order to set CS.
+31 C0 # xor ax, ax
+8E D8 # mov ds, ax
+8E C0 # mov es, ax
+8E D0 # mov ss, ax
+BC 00 7B # mov sp, 0x7B00
+FC # cld ; clear direction flag
+
+EA 26 7F 00 00 # jmp stage2_main
+
+
+#------------------------
+#[7E11]
+#:console_putc_16
+# input:
+# al: char to print
+#
+# Note: with QEMU+Seabios this does not flush the last character or
+# CRLF of a line until the first character is output on the next line
+# and that character cannot be another CRLF.
+53 # push bx
+50 # push ax
+
+# Prepare to use BIOS tty output interrupt.
+# Specify text page 00, 0 black background, 7 light grey text
+BB 00 07 # mov bx, 0x0007
+# Specify the `write character` BIOS routine
+B4 0E # mov ah, 0x0E
+
+3C 0A # cmp al, 0x0A
+75 06 # jne regular
+
+# convert LF to CR LF for BIOS output
+B0 0D # mov al, 0x0D
+CD 10 # int 0x10
+B0 0A # mov al, 0x0A
+
+#:regular
+CD 10 # int 0x10
+
+58 # pop ax
+5B # pop bx
+CB # retf
+
+
+#------------------------
+#[7E27]
+#:console_put_hex_16
+# input:
+# al: byte to print as hex
+#
+50 # push ax
+
+24 F0 # and al, 0xF0
+C0 E8 04 # shr al, 4
+3C 09 # cmp al, 9
+7F 04 # jg alpha1
+
+# numeral
+04 30 # add al, 0x30
+EB 02 # jmp print1
+
+#:alpha1
+04 37 # add al, 0x37
+
+#:print1
+9A 11 7E 00 00 # call console_putc_16
+
+58 # pop ax ; restore original al
+50 # push ax ;
+
+24 0F # and al, 0x0F
+3C 09 # cmp al, 9
+7F 04 # jg alpha2
+
+# numeral
+04 30 # add al, 0x30
+EB 02 # jmp print2
+
+#:alpha2
+04 37 # add al, 0x37
+
+#:print2
+9A 11 7E 00 00 # call console_putc_16
+
+58 # pop ax
+CB # retf
+
+
+
+#-------------
+#[7E51]
+#:boot_drive
+80
+
+#-------------
+#[7E52]
+#:max_head
+0F
+
+#-------------
+#[7E53]
+#:max_sector
+3F
+
+
+#------------------------
+#[7E54]
+#:get_drive_geometry
+# input:
+# dl: drive
+#
+06 # push es
+57 # push di
+
+# https://en.wikipedia.org/wiki/INT_13H#INT_13h_AH=08h:_Read_Drive_Parameters
+31 FF # xor di, di
+8E C7 # mov es, di
+B4 08 # mov ah, 8 ; get drive parameters
+CD 13 # int 0x13
+
+88 36 52 7E # mov [max_head], dh ; max_head
+80 E1 3F # and cl, 0x3f
+88 0E 53 7E # mov [max_sector], cl ; num_sectors
+
+5F # pop di
+07 # pop es
+CB # retf
+
+
+#------------------------
+#[7E6C]
+#:next_sector
+# inputs:
+# cx: cylinder/sector
+# dh: head
+#
+50 # PUSH_AX
+
+88 C8 # mov al, cl ; get sector number
+24 3F # and al, 0x3f
+3A 06 53 7E # cmp al, [max_sector]; if sector_num == max_sector
+74 04 # je next_head ; goto next_head
+FE C1 # inc cl ; else sector_num++;
+EB 28 # jmp next_sector_finish
+
+#:next_head
+3A 36 52 7E # cmp dh, [max_head] ; if head_num == max_head
+74 09 # je next_cylinder ; goto next_cyclinder
+FE C6 # inc dh ; else head_num++
+80 E1 C0 # and cl, 0xc0 ; sector_num = 1
+FE C1 # inc cl ;
+EB 19 # jmp next_sector_finish
+
+#:next_cylinder
+80 FD FF # cmp ch, 0xff ; if cylinder_low == 255
+74 0B # je next_cyl_high
+
+#:next_cyl_low
+30 F6 # xor dh, dh ; head_num = 0
+80 E1 C0 # and cl, 0xc0 ; sector_num = 0
+81 C1 01 01 # add cx, 0x0101 ; cylinder_low++, sector_num++
+EB 09 # jmp next_sector_finish
+
+#:next_cyl_high
+30 F6 # xor dh, dh ; head_num = 0
+81 E1 C0 00 # and cx, 0x00C0 ; cylinder_low = 0, sector_num = 0
+80 C1 41 # add cl, 0x41 ; cylinder_high++, sector_num++
+
+#:next_sector_finish
+58 # pop ax
+CB # retf
+
+
+#------------------------
+#[7EA5]
+#:read_sectors_16
+# inputs:
+# di: dest_addr
+# cx: cylinder/sector
+# dh: head
+# ax: num_sectors
+#
+# outputs:
+# di: next byte to write to
+# cx,dh: next disk sector to read from
+#
+50 # push ax
+53 # push bx
+56 # push si
+
+89 C6 # mov si, ax ; si=num_sectors
+89 FB # mov bx, di ; int 13 writes to bx
+
+#:read_one_loop
+8A 16 51 7E # mov dl, [boot_drive]
+B4 02 # mov ah, 2 ; rw mode = 02 (read)
+B0 01 # mov al, 1 ; num_sectors
+CD 13 # int 0x13
+72 F4 # jnc read_one_loop
+3C 01 # cmp al, 1
+75 F0 # jnz read_one_loop
+
+# advance and maybe continue
+9A 6C 7E 00 00 # call next_sector
+
+# we read one sector, advance
+81 C3 00 02 # add bx, 0x200
+
+4E # dec si ; num_sectors--
+75 E4 # jnz read_one_loop
+
+89 DF # mov di, bx
+
+5E # pop si
+5B # pop bx
+58 # pop ax
+CB # retf
+
+
+#------------------------
+#[7ECE]
+#:write_sectors_16
+# inputs:
+# si: source_addr
+# cx: cylinder/sector
+# dh: head
+# ax: num_sectors
+#
+# outputs:
+# si: next byte to read from
+# cx,dh: next disk sector to read from
+#
+50 # push ax
+53 # push bx
+57 # push di
+
+89 C7 # mov di, ax ; di=num_sectors
+89 F3 # mov bx, si ; int 13 reads from [bx]
+
+#:write_one_loop
+8A 16 51 7E # mov dl, [boot_drive]
+B4 03 # mov ah, 3 ; rw mode = 03 (write)
+B0 01 # mov al, 1 ; num_sectors
+CD 13 # int 0x13
+72 F4 # jnc write_one_loop
+3C 01 # cmp al, 1
+75 F0 # jnz write_one_loop
+
+# advance and maybe continue
+9A 6C 7E 00 00 # call next_sector
+
+# we write one sector, advance
+81 C3 00 02 # add bx, 0x200
+
+4F # dec di ; num_sectors--
+75 E4 # jnz write_one_loop
+
+89 DE # mov si, bx
+
+5F # pop di
+5B # pop bx
+58 # pop ax
+CB # retf
+
+
+#alignment only
+00
+
+#---------------------------------------------
+# The Global Descriptor Table for 32 bit mode.
+#---------------------------------------------
+#[7EF8]
+#:GDT_start
+00 00 00 00 00 00 00 00
+
+#:GDT_code32
+FF FF # limit 0:15
+00 00 # base 0:15
+00 # base 16:23
+9A # access byte 10011010b
+ # present=1 privilege=00 type=1
+ # code=1 conforming=0 readable=1 accessed=0
+CF # 11001111b
+ # granularity=1 32-bit-default=1 64-bit seg=0 AVL=0
+00 #
+
+#:GDT_data32
+FF FF # limit 0:15
+00 00 # base 0:15
+00 # base 16:23
+92 # access byte 10010010b
+ # present=1 privilege=00 type=1
+ # code=0 conforming=0 readable=1 accessed=0
+CF # flags, limit 16:19 11001111b
+ # granularity=1 32-bit-default=1 64-bit seg=0 AVL=0
+00 # base 24:31
+
+#:GDT_code16
+FF FF # limit 0:15
+00 00 # base 0:15
+00 # base 16:23
+9A # access byte 10011010b
+ # present=1 privilege=00 type=1
+ # code=1 conforming=0 readable=1 accessed=0
+8F # 10001111b
+ # granularity=1 32-bit-default=0 64-bit seg=0 AVL=0
+00 #
+
+#:GDT_data16
+FF FF # limit 0:15
+00 00 # base 0:15
+00 # base 16:23
+92 # access byte 10010010b
+ # present=1 privilege=00 type=1
+ # code=0 conforming=0 readable=1 accessed=0
+8F # flags, limit 16:19 10001111b
+ # granularity=1 32-bit-default=0 64-bit seg=0 AVL=0
+00 # base 24:31
+
+#------
+#[7F20]
+#:GDT_locator
+27 00 # length
+F8 7E 00 00 # GDT_start
+
+
+#------------------------
+#[7F26]
+#:stage2_main
+# inputs:
+# dl: boot_drive
+#
+# Load the kernel and jump to it
+88 16 51 7E # mov [boot_drive], dl
+9A 54 7E 00 00 # call get_drive_geometry()
+BF 00 80 # mov di, 0x8000 ; place remaining code after MBR in memory
+B8 07 00 # mov ax, 0x0007 ; num_sectors = 7
+B9 02 00 # mov cx, 0x0002 ; cylinder = 0, sector_num = 0x02
+B6 00 # mov dh, 0 ; head = 0
+
+# XXX disabled - stage1 compiles code
+90 90 90 90 90
+#9A A5 7E 00 00 # call read_sectors_16
+
+# start 32bit mode
+B8 01 24 # mov ax,2401h # enable A20 line
+CD 15 # int 15h
+
+FA # cli
+0F 01 16 20 7F # lgdt GDT_locator
+0F 20 C0 # mov eax, cr0
+66 83 C8 01 # or eax, 0x01
+0F 22 C0 # mov cr0, eax
+EA 59 7F 08 00 # jmp setup_32bit ; sets CS
+
+#------
+#[7F59]
+#:setup_32bit
+66 B8 10 00 # mov ax, 0x0010 ; data descriptor
+8E D8 # mov ds, ax
+8E D0 # mov ss, ax
+8E C0 # mov es, ax
+8E E0 # mov fs, ax
+8E E8 # mov gs, ax
+BD 00 00 00 08 # mov ebp, 0x08000000
+89 EC # mov esp, ebp
+
+9A 7C 7F 00 00 08 00 # call setup_interrupt_handlers
+EA A1 8A 00 00 08 00 # jmp internalshell
+
+
+#----------------------------------------
+#[7F7C]
+#:setup_interrupt_handlers
+53 # push ebx
+
+# handle the timer interrupt 08
+BB 40 00 01 00 # mov ebx, &interrupt_table[08]
+66 C7 03 BC 7F # mov word [ebx + 0], low_address stub_interrupt_handler
+66 C7 43 06 00 00 # mov word [ebx + 6], high_address
+66 C7 43 02 08 00 # mov word [ebx + 2], code_segment = 0x0800
+C6 43 05 8E # mov byte [ebx + 5], flags = 8E
+
+# handle int 80
+BB 00 04 01 00 # mov ebx, &interrupt_table[80]
+66 C7 03 D8 80 # mov word [ebx + 0], low_address syscall_interrupt_handler
+66 C7 43 06 00 00 # mov word [ebx + 6], high_address
+66 C7 43 02 08 00 # mov word [ebx + 2], code_segment = 0x0800
+C6 43 05 8E # mov byte [ebx + 5], flags = 8E
+
+# load the interrupt table
+FA # cli
+0F 01 1D BD 7F 00 00 # lidt IDT_locator_32
+FB # sti
+5B # pop ebx
+CB # retf
+
+
+#----------------------------------------
+#[7FBC]
+#:stub_interrupt_handler
+CF # iret
+
+
+#----------------------------------------
+#[7FBD]
+#:IDT_locator_32
+FF 07 # length
+00 00 01 00 # IDT_start
+
+# unused
+00 00
+
+
+#------------------------------------------------------------
+# 32 -> 16 -> 32 bit switching functions
+#------------------------------------------------------------
+# When switching between real mode and
+# protected, registers are stored here:
+#
+# 7B14 edx
+# 7B10
+# 7B0C
+# 7B08 eax
+# 7B04 esp
+#
+# 7B00 <- top of real mode stack
+
+#----------------------------------------
+#[7FC5]
+#:enter_16bit_real
+FA # cli
+A3 08 7B 00 00 # mov [0x7B08], eax ; preserve so we can use these locally
+89 15 14 7B 00 00 # mov [0x7B14], edx ;
+5A # pop edx ; capture return address
+89 25 04 7B 00 00 # mov [0x7B04], esp ; capture stack
+
+# The following far jump sets CS to a 16-bit protected mode selector
+# and the segment registers are also set to 16-bit protected mode selectors.
+# This is done prior to entering real mode.
+EA DF 7F 00 00 18 00 # jmp 0x18:setup_16bit
+#------
+#[7FDF]
+#:setup_16bit
+B8 20 00 # mov eax, 0x0020
+8E D0 # mov ss, eax
+8E D8 # mov ds, eax
+8E C0 # mov es, eax
+8E E8 # mov gs, eax
+8E E0 # mov fs, eax
+BC 00 7B # mov sp, 0x7B00
+0F 20 C0 # mov eax, cr0
+66 83 E0 FE # and eax, 0xfffffffe ; clear protected mode
+0F 22 C0 # mov cr0, eax
+# The following far jump sets CS to a 16-bit real mode segment
+# and the segment registers are also set to real mode segments.
+EA 00 80 00 00 # jmp 0000:XXXX real_mode
+
+# [7DFE]
+# Unused
+00 00
+
+#------
+#[8000]
+#:real_mode
+B8 00 00 # mov ax, 0x0
+8E D8 # mov ds, ax
+8E E0 # mov fs, ax
+8E E8 # mov gs, ax
+8E D0 # mov ss, ax
+8E C0 # mov es, ax
+BC 00 7B # mov sp, 0x7B00
+FA # cli
+0F 01 1E 22 80 # lidt IDT_locator_16
+FB # sti
+# Using retf to set CS comes from here:
+# https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode
+# This page recommends a far jump followed by sti:
+# https://www.sudleyplace.com/pmtorm.html
+6A 00 # push 0x0000 (2 bytes!) CS to return to
+52 # push dx IP to return to
+A1 08 7B # mov ax, [0x7B08] ; restore from above
+8B 16 14 7b # mov dx, [0x7B14]
+CB # retf
+
+#------
+#[8022]
+#:IDT_locator_16
+FF 03
+00 00 00 00
+
+
+#----------------------------------------
+#[8028]
+#:resume_32bit_mode
+FA # cli
+A3 08 7B # mov [0x7B08], ax ; preserve, they might be return values from 16 bit
+89 16 14 7b # mov [0x7B14], dx
+5A # pop dx ; carry the return IP in dx
+58 # pop ax ; CS
+0F 01 16 20 7F # lgdt GDT_locator
+0F 20 C0 # mov eax, cr0
+66 83 C8 01 # or eax, 0x01 ; enable protected mode
+0F 22 C0 # mov cr0, eax
+EA 46 80 08 00 # jmp restore_32bit
+#------
+#[8046]
+#:restore_32bit
+B8 10 00 00 00 # mov eax, 0x0010 ; data descriptor
+8E D8 # mov ds, eax
+8E D0 # mov ss, eax
+8E C0 # mov es, eax
+8E E0 # mov fs, eax
+8E E8 # mov gs, eax
+8B 25 04 7B 00 00 # mov esp, [0x7B04] ; restore, (saved in enter_16bit_mode)
+9A 7C 7F 00 00 08 00 # call setup_interrupt_handlers
+52 # push edx ; setup our return location
+# These restore the 16 bit portion of these registers, which may be a
+# return value from a 16 bit function, and they also restore any previous high
+# bits that were stored by enter_16bit_mode so these registers need not be
+# saved when going to 16 bit mode and back if you want them left alone.
+A1 08 7B 00 00 # mov eax, [0x7B08] ; restore, (saved at top of this function)
+8B 15 14 7B 00 00 # mov edx, [0x7B14]
+C3 # ret
+
+
+#------------------------
+#[806F]
+#:console_putc
+#
+E8 51 FF FF FF # CALL enter_16bit_real, next=[8074]
+9A 11 7E 00 00 # CALL console_putc_16(al)
+9A 28 80 00 00 # CALL resume_32bit_mode
+CB # RETF
+
+
+#------------------------
+#[807F]
+#:console_put_hex
+E8 41 FF FF FF # CALL enter_16bit_real, next=[8084]
+9A 27 7E 00 00 # CALL console_put_hex_16(al)
+9A 28 80 00 00 # CALL resume_32bit_mode
+CB # RETF
+
+
+#------------------------
+#[808F]
+#:console_puts
+# inputs
+# ds:si: string to print
+#:puts_loop
+50 # push eax
+56 # push esi
+8A 06 # mov al, [esi]
+3C 00 # cmp al, 0
+74 0A # jz end_puts_loop
+9A 6F 80 00 00 08 00 # call console_putc
+46 # inc esi
+EB F0 # jmp puts_loop
+#:end_puts_loop
+B0 0A # mov al, 0A
+9A 6F 80 00 00 08 00 # call console_putc
+5E # pop esi
+58 # pop eax
+CB # RETF
+
+
+#------------------------
+#[80AD]
+#:read_sectors
+# inputs:
+# di: dest_addr
+# cx: cylinder/sector
+# dh: head
+# ax: num_sectors
+#
+E8 13 FF FF FF # CALL enter_16bit_real, next=[80B2]
+9A A5 7E 00 00 # CALL read_sectors_16
+9A 28 80 00 00 # CALL resume_32bit_mode
+CB # RETF
+
+
+#------------------------
+#[80BD]
+#:write_sectors
+# inputs:
+# si: source_addr
+# cx: cylinder/sector
+# dh: head
+# ax: num_sectors
+#
+E8 03 FF FF FF # CALL enter_16bit_real, next=[80C2]
+9A CE 7E 00 00 # CALL write_sectors_16
+9A 28 80 00 00 # CALL resume_32bit_mode
+CB # RETF
+
+#------------------------
+#[80CD]
+#:reboot
+E8 F3 FE FF FF # call enter_16bit_real, next=[80D2]
+FA # cli
+EA F0 FF 00 F0 # ljmp $F000:FFF0 ; reboot
+
+
+#------------------------
+#[80D8]
+#:syscall_interrupt_handler
+#
+3C 01 # cmp al, 1
+75 08 # jne try next
+9A B7 86 00 00 08 00 # call handle_syscall_exit
+CF # iret
+
+3C 02 # cmp al, 2
+75 08 # jne try next
+9A B0 84 00 00 08 00 # call handle_syscall_fork
+CF # iret
+
+3C 03 # cmp al, 3
+75 08 # jne try next
+9A 5B 83 00 00 08 00 # call handle_syscall_read
+CF # iret
+
+3C 04 # cmp al, 4
+75 08 # jne try next
+9A 3D 84 00 00 08 00 # call handle_syscall_write
+CF # iret
+
+3C 05 # cmp al, 5
+75 08 # jne try next
+9A 94 81 00 00 08 00 # call handle_syscall_open
+CF # iret
+
+3C 06 # cmp al, 6
+75 08 # jne try next
+9A 5E 82 00 00 08 00 # call handle_syscall_close
+CF # iret
+
+3C 07 # cmp eax, 7
+75 08 # jne try next
+9A 0B 87 00 00 08 00 # call handle_syscall_waitpid
+CF # iret
+
+3C 0B # cmp eax, B
+75 08 # jne try next
+9A 1E 85 00 00 08 00 # call handle_syscall_execve
+CF # iret
+
+3C 0C # cmp al, C
+75 08 # jne try next
+9A 60 86 00 00 08 00 # call handle_syscall_chdir
+CF # iret
+
+3C 13 # cmp al, 0x13
+75 08 # jne try next
+9A 25 87 00 00 08 00 # call handle_syscall_lseek
+CF # iret
+
+3C 2D # cmp al, 2D
+75 08 # jne try next
+9A 0E 84 00 00 08 00 # call handle_syscall_brk
+CF # iret
+
+3C 21 # cmp al, 0x21
+75 08 # jne try next
+9A 6D 87 00 00 08 00 # call handle_syscall_access
+CF # iret
+
+3C 27 # cmp al, 0x27
+75 08 # jne syscall_ok
+9A 83 87 00 00 08 00 # call handle_syscall_mkdir
+CF # iret
+
+# wait4
+3C 72 # cmp eax, 0x72
+75 05 # jne try next
+31 C0 # xor eax, eax
+89 01 # mov [ecx], eax
+CF # iret
+
+3C B7 # cmp al, 0xB7
+75 08 # jne syscall_ok
+9A 99 87 00 00 08 00 # call handle_syscall_getcwd
+CF # iret
+
+#:syscall_ok
+# return success for all unimplemented syscalls
+31 C0 # xor eax, eax
+CF # iret
+
+
+#------
+#[818C]
+#:next_filenum
+04 00 00 00
+
+#------
+#[8190]
+#:next_file_address
+00 00 00 54
+
+#----------------------------------------
+#[8194]
+#:handle_syscall_open
+# inputs:
+# ebx: filename
+# ecx: flags
+#
+53 # push ebx
+51 # push ecx
+56 # push esi
+57 # push edi
+
+9A 76 82 00 00 08 00 # call absolute_path
+
+F7 C1 40 00 00 00 # test ecx, 0x40 ; 0x40 is O_CREAT
+74 72 # jz open_read
+
+# Create new file
+
+# Exit with error if directory does not exist
+
+# Go the end of filename
+89 DE # mov esi, ebx
+#:end_loop
+AC # lodsb
+3C 00 # cmp al, 0
+75 FB # jne end_loop
+# Look in reverse for last slash
+4E # dec esi
+FD # std ; go backwards
+#:find_slash_loop
+AC # lodsb
+3C 2F # cmp al, '/'
+75 FB # jne find_slash_loop
+# If first slash at start, its root, so it exists
+FC # cld
+46 # inc esi
+39 DE # cmp esi, ebx
+74 1C # je after_dir_lookup
+# Zero out slash
+31 C0 # xor eax, eax
+89 F7 # mov edi, esi
+AA # stosb
+# Lookup directory
+9A 13 83 00 00 08 00 # call find_file ; eax=find_file(ebx)
+# Restore first char
+C6 47 FF 2F # mov byte [edi - 1], 0x2f
+83 F8 FF # cmp eax, -1
+75 07 # jne after_dir_lookup
+EA 59 82 00 00 08 00 # jmp syscall_open_finish_fail
+
+#:after_dir_lookup
+
+# copy filename to new slot
+89 DE # mov esi, ebx
+BF 00 00 20 00 # mov edi, 0x0200000
+A1 8C 81 00 00 # mov eax, [&next_filenum]
+C1 E0 0A # shl eax, 0a
+01 C7 # add edi, eax
+B9 00 04 00 00 # mov ecx, 0x0000400
+F3 A4 # rep movsb
+
+# set address of file
+BF 00 00 00 01 # mov edi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
+A1 8C 81 00 00 # mov eax, [&next_filenum]
+C1 E0 04 # shl eax, 04
+01 C7 # add edi, eax ; pfile_descriptor += sizeof(file_descriptor) * next_filenum
+8B 0D 90 81 00 00 # mov ecx, [next_file_address]
+
+89 4F 04 # mov [edi+4], ecx ; pfile_descriptor->file_addr = ecx
+
+31 C0 # xor eax, eax
+89 47 08 # mov [edi+8], eax ; pfile_descriptor->length = 0
+
+A1 8C 81 00 00 # mov eax, [next_filenum] ; return next_filenum
+FF 05 8C 81 00 00 # inc [next_filenum]
+EB 18 # jmp syscall_open_finish
+
+#open_read
+9A 13 83 00 00 08 00 # call find_file
+83 F8 FF # cmp eax, -1
+74 34 # je syscall_open_finish_fail
+
+89 C1 # mov ecx, eax
+# set read offset to start of file
+BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
+C1 E1 04 # shl ecx, 04
+01 CE # add esi, ecx ; pfile_descriptor += sizeof(file_descriptor) * filenum
+
+#:syscall_open_finish
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 20 02 02 00 # add esi, 0x0020220 ; pproc_descriptor = &pproc_descriptor[current_process_num].open_files[4]
+
+6A 04 # push 0x04 ; start at fd=4
+59 # pop ecx
+#:find_slot_loop
+8B 1E # mov ebx, [esi] ; get file number of fd slot
+85 DB # test ebx, ebx ; is this fd slot available?
+74 06 # jz got_slot
+41 # inc ecx ; no, go to next slot
+83 C6 08 # add esi, 0x08
+EB F4 # jmp find_slot_loop
+#:got_slot
+89 06 # mov [esi], eax ; store file number in slot
+89 C8 # mov eax, ecx ; return fd
+
+31 C9 # xor ecx, ecx ; set current file offset to zero
+89 4E 04 # mov [esi+0x4], ecx
+
+#--------
+#[8259]
+#:syscall_open_finish_fail
+
+5F # pop edi
+5E # pop esi
+59 # pop ecx
+5B # pop ebx
+CB # ret
+
+
+#----------------------------------------
+#[825E]
+#:handle_syscall_close
+# inputs:
+# ebx: fd
+
+57 # push edi
+8B 3D 1A 85 00 00 # mov edi, [&next_process_num]
+4F # dec edi = current process
+C1 E7 0C # shl edi, 0x0C
+81 C7 00 02 02 00 # add edi, 0x00020200 ; edi = all_procs[current_process_num].open_files
+31 C0 # xor eax, eax
+89 04 DF # mov [edi+ebx*8], eax ; open_files[fd].global_index = 0
+5F # pop edi
+CB # ret
+
+
+#----------------------------------------
+#[8276]
+#:absolute_path
+# inputs:
+# ebx: path
+# outputs:
+# ebx: absolute path
+#
+50 # push eax
+52 # push edx
+56 # push esi
+57 # push edi
+
+BF 00 02 04 00 # mov edi, 0x00040200 ; scratch buffer
+57 # push edi
+
+# if absolute path, skip prefixing current directory
+80 3B 2F # cmp [ebx], '/'
+74 18 # je strcpy_path_arg
+
+# get cwd
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 00 01 02 00 # add esi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
+
+#:strcpy_cwd_loop
+AC # lodsb
+84 C0 # test al, al
+74 03 # jz strcpy_path_arg
+AA # stosb
+EB F8 # jmp strcpy_cwd_loop
+
+#:strcpy_path_arg
+89 DE # mov esi, ebx
+# skip leading ./
+66 81 3E 2E 2F # cmp word [esi], 0x2F2E
+75 02 # jne strcpy_path
+46 # inc esi
+46 # inc esi
+
+#:strcpy_path
+31 DB # xor ebx, ebx ; init last_char
+#:strcpy_path_loop
+AC # lodsb
+3C 2F # cmp al, '/'
+75 05 # jne ok_path_char
+80 FB 2F # cmp bl, '/'
+74 01 # je skip_extra_slash
+#:ok_path_char
+AA # stosb
+#:skip_extra_slash
+84 C0 # test al, al
+74 04 # jz maybe_strip_ending_slash
+88 C3 # mov bl, al ; save last_char
+EB ED # jmp strcpy_path_loop
+
+#:maybe_strip_ending_slash
+80 FB 2F # cmp bl, '/'
+75 05 # jne handle_dots
+31 C0 # xor eax, eax
+4F # dec edi
+4F # dec edi
+AA # stosb
+
+# handle /. and /..
+#:handle_dots
+5A # pop edx ; record first parent
+52 # push edx
+
+#:handle_dots_loop
+5E # pop esi ; get start location
+56 # push esi ; save start location
+
+## find_slash
+AC # lodsb
+3C 00 # cmp al, 0
+74 33 # je absolute_path_finish
+3C 2F # cmp al, '/'
+75 F7 # jne find_slash
+
+#:found_slash
+AC # lodsb
+# check for /. or /..
+3C 00 # cmp al, 0
+74 2A # je absolute_path_finish
+3C 2E # cmp al, '.'
+74 06 # je dot_or_dotdot
+89 F2 # mov edx, esi ; record start of parent
+4A # dec edx ; go back to slash
+4A # dec edx
+EB E8 # jmp find_slash
+#:dot_or_dotdot
+AC # lodsb
+3C 2E # cmp al, '.'
+75 0A # jne remove_slashdot
+
+#:remove_parent
+89 D7 # mov edi, edx
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 FA # jne copy
+EB D7 # jmp handle_dots_loop
+
+#:remove_slashdot
+3C 00 # cmp al, 0
+75 01 # jne not_ending_slashdot
+4E # dec esi ; go back to null
+#:not_ending_slashdot
+89 F7 # mov edi, esi
+4F # dec edi
+4F # dec edi
+#:copy_over_slashdot
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 FA # jne copy_over_slashdot
+EB C6 # jmp handle_dots_loop
+
+#:absolute_path_finish
+5B # pop ebx
+
+# restore / if necessary
+80 3B 00 # cmp byte [ebx], 0
+75 05 # jne abs_path_done
+66 C7 03 2F 00 # mov word [ebx], 0x002F
+
+#:abs_path_done
+5F # pop edi
+5E # pop esi
+5A # pop edx
+58 # pop eax
+CB
+
+
+#----------------------------------------
+#[8313]
+#:find_file
+# inputs:
+# ebx: file_name
+# outputs:
+# eax: filenum
+#
+51 # push ecx
+52 # push edx
+56 # push esi
+57 # push edi
+
+A1 8C 81 00 00 # mov eax, [next_filenum]
+48 # dec eax
+89 DE # mov esi, ebx
+
+#:checkfile
+83 F8 03 # cmp eax, 3
+74 17 # je not_found
+89 C7 # mov edi, eax
+C1 E7 0A # shl edi, 0x0a
+81 C7 00 00 20 00 # add edi, 0x0200000
+9A C6 87 00 00 08 00 # call strcmp
+74 08 # je find_file_finish
+48 # dec eax
+EB E4 # jmp checkfile
+
+#:not_found
+B8 FF FF FF FF # mov eax, 0xffffffff
+
+#:find_file_finish
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+CB # ret
+
+
+#------------------------------------------------------------
+#[8345]
+#:fd_to_file_index
+# inputs:
+# ebx: file descriptor number
+# outputs:
+# ebx: global file index
+57 # push edi
+8B 3D 1A 85 00 00 # mov edi, [&next_process_num]
+4F # dec edi = current process
+C1 E7 0C # shl edi, 0x0C
+81 C7 00 02 02 00 # add edi, 0x00020200 ; edi = all_procs[current_process_num].open_files
+8B 1C DF # mov ebx, [edi+ebx*8]
+5F # pop edi
+CB # ret
+
+
+#------------------------------------------------------------
+#[835B]
+#:handle_syscall_read
+# inputs:
+# ecx: *return_char
+# ebx: file
+# edx: length
+#
+53 # push ebx
+51 # push ecx
+52 # push edx
+56 # push esi
+57 # push edi
+
+51 # push ecx ; we need this later to return char
+83 FB 00 # cmp ebx, 0
+75 5F # jne read_memfile
+
+# stdin disk position is stored in fd 0
+# get current position
+BB 00 00 00 01 # mov ebx, 0x01000000
+66 8B 0B # mov cx, [ebx]
+8A 73 02 # mov dh, [ebx+2]
+31 C0 # xor eax, eax
+66 8B 43 04 # mov ax, [ebx+4]
+
+#end of sector?
+66 3D FF 01 # cmp ax, 0x01ff
+74 04 # je read_next_sector
+
+#:nextchar
+66 40 # inc ax
+EB 2A # jmp getchar
+
+#:read_next_sector
+BF 00 A0 00 00 # mov edi, 0x000A000
+B8 01 00 00 00 # mov eax, 0x0001 ; num_sectors = 1
+9A AD 80 00 00 08 00 # call read_sectors
+# save new location and offset
+66 89 0b # mov [ebx], cx
+88 73 02 # mov [ebx+2], dh
+31 C0 # xor eax, eax
+
+# move block to device buffer
+BE 00 A0 00 00 # mov esi, 0x000A000
+BF 00 00 04 00 # mov edi, 0x0040000
+B9 00 02 00 00 # mov ecx, 0x0000200
+F3 A4 # rep movsb
+
+#:getchar
+66 A3 04 00 00 01 # mov [0x01000004], ax
+59 # pop ecx
+BB 00 00 04 00 # mov ebx, 0x40000 ; device buffer
+89 C6 # mov esi, eax ; offset
+8A 04 33 # mov al, [ebx+esi+0]
+88 01 # mov [ecx], al
+B8 01 00 00 00 # mov eax, 1
+EB 43 # jmp syscall_read_finish
+
+#:read_memfile
+89 D8 # mov eax, ebx ; eax = fd
+9A 45 83 00 00 08 00 # call fd_to_file_index ; ebx = global file index
+# get pointer to global file
+BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
+C1 E3 04 # shl ebx, 04
+01 DE # add esi, ebx ; pfile_descriptor += sizeof(file_descriptor) * filenum
+
+# prepare to read
+5F # pop edi ; edi = p_dst
+8B 5E 04 # mov ebx, [esi+4] ; ebx = pfile_descriptor->file_address
+89 D9 # mov ecx, ebx ;
+03 4E 08 # add ecx, [esi+0x08] ; ecx = file_address + length
+49 # dec ecx ; ecx = last address to read
+
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 04 02 02 00 # add esi, 0x0020204
+C1 E0 03 # shl eax, 3
+01 C6 # add esi, eax ; esi = &all_procs[current_proc_num].files[eax].current_offset
+
+03 1E # add ebx, [esi] ; ebx = file_addr + current_offset
+87 F3 # xchg esi, ebx ; esi = p_src, ebx = &pproc_descriptor->offset
+31 C0 # xor eax, eax ; bytes_read = 0
+
+#:syscall_read_loop
+39 CE # cmp esi, ecx ; past the end?
+77 07 # ja syscall_read_finish
+
+A4 # movsb
+40 # inc eax ; bytes_read++
+FF 03 # inc long [ebx] ; (*pcurrent_offset)++
+4A # dec edx ; length_to_read--
+75 F5 # jnz syscall_read_loop
+
+#:syscall_read_finish
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+CB # ret
+
+
+
+#------------------------------------------------------------
+#[840E]
+#:handle_syscall_brk
+56 # push esi
+
+A1 1A 85 00 00 # mov eax, [&next_process_num]
+48 # dec eax = current process
+
+BE 00 00 02 00 # mov esi, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
+C1 E0 0C # shl eax, 0x0C
+01 C6 # add esi, eax ; pproc_descriptor += sizeof(proc_descriptor) * procnum
+
+85 DB # test ebx, ebx ; if ebx == 0, just return the current brk
+74 15 # jz get_brk
+
+# set
+# initialize memory to zero
+57 # push edi
+8B 7E 04 # mov edi, [esi+4]
+31 C0 # xor eax, eax
+#:init_loop
+39 DF # cmp edi, ebx
+74 03 # je init_done
+AA # stosb
+EB F9 # jmp init_loop
+#:init_done
+5F # pop edi
+
+89 5E 04 # mov [esi+4], ebx
+89 D8 # mov eax, ebx
+5E # pop esi
+CB # ret
+
+#:get_brk
+8B 46 04 # mov eax, [esi+4] ; pproc_descriptor->brk
+5E # pop esi
+CB # ret
+
+
+#------------------------------------------------------------
+#[843D]
+#:handle_syscall_write
+# inputs:
+# ebx: file
+# ecx: address of char to write
+# edx: num bytes to write
+51 # push ecx
+52 # push edx
+56 # push esi
+57 # push edi
+
+31 C0 # xor eax, eax ; bytes_written = 0
+
+83 FB 02 # cmp ebx, 02 ; std file?
+7F 14 # jg write_memfile
+
+# stdout,stderr -> console_out
+#:std_loop
+85 D2 # test edx, edx
+74 5B # jz syscall_write_finish
+50 # push eax ; save num_written
+8A 01 # mov al, [ecx]
+9A 6F 80 00 00 08 00 # call console_putc
+58 # pop eax ; restore num_written
+
+40 # inc eax ; num_written++
+41 # inc ecx ; p_dst++
+4A # dec edx ; count--
+EB EC # jmp std_loop
+
+#:write_memfile
+89 CE # mov esi, ecx
+
+# use ecx as pointer to fd current offset
+8B 0D 1A 85 00 00 # mov ecx, [&next_process_num]
+49 # dec ecx = current process
+C1 E1 0C # shl ecx, 0x0C
+81 C1 04 02 02 00 # add ecx, 0x0020204
+53 # push ebx
+C1 E3 03 # shl ebx, 3
+01 D9 # add ecx, ebx ; ecx = &all_procs[current_proc_num].files[ebx].current_offset
+5B # pop ebx
+
+# lookup global file index from file descriptor
+9A 45 83 00 00 08 00 # call fd_to_file_index
+C1 E3 04 # shl ebx, 04
+81 C3 00 00 00 01 # add ebx, 0x01000000 ; pfile_descriptor += sizeof(file_descriptor) * filenum
+
+8B 7B 04 # mov edi, [ebx+4] ; edi = pfile_descriptor->file_address
+03 39 # add edi, [ecx] ; edi = file_addr + current_offset
+#:write_loop
+85 D2 # test edx, edx
+74 19 # jz syscall_write_finish
+A4 # movsb
+FF 01 # inc long [ecx] ; current_offset++
+# If current offset is past previous file length, then increase length
+50 # push eax
+8B 01 # mov eax, [ecx]
+3B 43 08 # cmp eax, [ebx+0x8]
+7E 09 # jle skip_lengthen
+FF 43 08 # inc long [ebx+0x8] ; file_length++
+FF 05 90 81 00 00 # inc long [next_file_address]
+#:skip_lengthen
+58 # pop eax
+40 # inc eax ; num_written++
+4A # dec edx
+EB E3 # jmp write_loop
+
+#:syscall_write_finish
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+CB # ret
+
+
+#------
+#[84AC]
+#:next_save_process_address
+00 00 00 30
+
+#----------------------------------------
+#[84B0]
+#:handle_syscall_fork
+53 # push ebx
+51 # push ecx
+52 # push edx
+56 # push esi
+57 # push edi
+55 # push ebp
+
+A1 1A 85 00 00 # mov eax, [&next_process_num]
+48 # dec eax = current process
+89 C2 # mov edx, eax
+BF 00 00 02 00 # mov edi, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
+C1 E0 0C # shl eax, 0x0C
+01 C7 # add edi, eax ; pproc_descriptor += sizeof(proc_descriptor) * procnum
+
+8b 77 04 # mov esi, [edi+0x4] ; save brk pointer
+89 77 14 # mov [edi+0x14], esi
+89 E6 # mov esi, esp
+89 77 0C # mov [edi+0xC], esi ; save stack pointer so we can return again later
+FF 47 10 # inc [edi+0x10] ; fork = true
+
+A1 AC 84 00 00 # mov eax, [next_save_process_address] ; set save stack location
+89 47 24 # mov [edi+0x24], eax
+
+B9 00 00 00 08 # mov ecx, 0x08000000
+29 F1 # sub ecx, esi ; compute save stack length
+01 0D AC 84 00 00 # add [next_save_process_address], ecx
+89 4F 28 # mov [edi+0x28], ecx
+89 C7 # mov edi, eax
+F3 A4 # rep movsb ; save stack
+
+# copy current process image to storage
+89 D0 # mov eax, edx ; restore current process num
+C1 E0 0C # shl eax, 0x0C
+05 00 00 02 00 # add eax, 0x0020000
+8B 30 # mov esi, [eax] ; esi = pproc_descriptor->process_address
+
+8B 48 14 # mov ecx, [eax+0x14] ; process_length = brk - process_address
+29 F1 # sub ecx, esi
+89 78 1C # mov [eax+0x1C], edi ; save address of saved process memory
+89 48 20 # mov [eax+0x20], ecx ; save length of process memory
+01 0D AC 84 00 00 # add [next_save_process_address], ecx
+F3 A4 # rep movsb ; copy current process image to storage
+
+31 C0 # xor eax, eax ; return as child, we'll return again as parent when child exits
+5D # pop ebp
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+CB # ret
+
+
+#------
+#[851A]
+#:next_process_num
+01 00 00 00
+
+#----------------------------------------
+#[851E]
+#:handle_syscall_execve
+# inputs:
+# ebx: program_name
+# ecx: char **args
+# edx: env
+#
+
+A1 1A 85 00 00 # mov eax, [next_process_num]
+3C 01 # cmp al, 1
+75 0A # jne not_first_process
+
+# first process
+BD 00 10 02 00 # mov ebp, 0x00021000 ; ebp = &proc_descriptor[1]
+89 65 08 # mov [ebp+0x8], esp ; save original stack pointer before pushing args
+EB 23 # jmp prepare_stack
+
+# not_first_process
+# check if current process forked or not.
+# if so, create new process, if not overlay current
+48 # dec eax ; eax = current_process
+C1 E0 0C # shl eax, 0x0C
+05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
+8B 68 10 # mov ebp, [eax+0x10] ; create_new_process = pproc->forked
+85 ED # test ebp, ebp ; did current process fork?
+75 0B # jnz forked
+
+#not_forked
+8B 60 0C # mov esp, [eax+0xC] ; no fork so reset initial stack to same as current process
+A1 1A 85 00 00 # mov eax, [next_process_num]
+48 # dec eax
+EB 08 # jump prepare_stack
+
+#:forked
+FF 48 10 # dec [eax+0x10] ; fork handled so reset: fork = false
+A1 1A 85 00 00 # mov eax, [next_process_num]
+
+
+#:prepare_stack
+# eax=process number to use
+# --- env ---
+8B 3D AC 84 00 00 # mov edi, [next_save_process_address]
+6A 00 # push 0 ; push end of env
+#:push_env_loop
+# copy env arg to memory for this process
+8B 32 # mov esi, [edx]
+85 F6 # test esi, esi
+74 0F # jz end_env_loop
+57 # push edi ; push p_arg
+51 # push ecx
+B9 00 01 00 00 # mov ecx, 0x00000100 ; memory per arg
+F3 A4 # rep movsb ; copy to new memory
+59 # pop ecx
+83 C2 04 # add edx, 4
+EB EB # jmp push_env_loop
+
+
+#:end_env_loop
+# --- args ---
+6A 00 # push 0 ; push end of args
+# count args
+31 C0 # xor eax, eax ; passed_args = 0
+#:countloop
+83 39 00 # cmp long [ecx], 0
+74 06 # jz push_args
+40 # inc eax
+83 C1 04 # add ecx, 4
+EB F5 # jmp countloop
+
+# push_args
+89 C2 # mov edx, eax ; save eax (can't push)
+#:push_args_loop
+83 E9 04 # sub ecx, 4
+
+# copy arg to memory for this process
+8B 31 # mov esi, [ecx]
+
+57 # push edi ; push p_arg
+
+51 # push ecx
+B9 00 01 00 00 # mov ecx, 0x00000100 ; memory per arg
+F3 A4 # rep movsb
+59 # pop ecx
+48 # dec eax
+75 EE # jnz push_args_loop
+
+# finish with argc
+89 D0 # mov eax, edx ; restore eax
+50 # push eax = argc
+
+# get current process descriptor
+A1 1A 85 00 00 # mov eax, [next_process_num]
+48 # dec eax
+50 # push eax ; save current process num
+C1 E0 0C # shl eax, 0x0C
+05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[current_process_num]
+
+89 3D AC 84 00 00 # mov [next_save_process_address], edi
+
+# copy cwd from current process
+05 00 01 00 00 # add eax, 0x100
+89 C6 # mov esi, eax
+05 00 10 00 00 # add eax, 0x1000
+89 C7 # mov edi, eax
+#loop
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 FA # jne loop
+
+58 # pop eax ; restore current process num
+40 # inc eax ; eax = new process id
+
+# prepare process image in memory
+50 # push eax ; save new process id
+# get file address and length
+9A 76 82 00 00 08 00 # call absolute_path
+9A 13 83 00 00 08 00 # call find_file ; eax=find_file(ebx)
+
+# zero process memory.
+# Do this after looking up file name because that may come from process memory.
+50 # push eax
+57 # push edi
+31 C0 # xor eax, eax
+BF 00 80 04 08 # mov edi, 0x08048000
+B9 00 80 FB 26 # mov ecx, 0x26FB8000
+F3 AA # rep stosb
+5F # pop edi
+58 # pop eax
+
+C1 E0 04 # shl eax, 04 ; pfile_descriptor = sizeof(file_descriptor) * filenum
+05 00 00 00 01 # add eax, 0x01000000 ; pfile_descriptor += &file_descriptors[0]
+
+8B 40 04 # mov eax, [eax + 0x4] ; eax = pfile_descriptor->file_address
+89 C3 # mov ebx, eax ; save file address
+31 C9 # xor ecx, ecx
+66 8B 48 2C # mov cx, [eax + 0x2C] ; get number of program headers
+8B 50 18 # mov edx, [eax + 0x18] ; get process entry address
+03 40 1C # add eax, [eax + 0x1C] ; calc first program header address
+
+#:program_header_loop
+51 # push ecx ; save program header count
+8B 70 04 # mov esi, [eax + 4] ; get segment file source offset
+01 DE # add esi, ebx ; calc segment file address
+8B 78 08 # mov edi, [eax + 8] ; get segment memory destination address
+8B 48 10 # mov ecx, [eax + 0x10] ; get segment length
+F3 A4 # rep movsb
+
+83 C0 20 # add eax, 0x20 ; go to next program header
+59 # pop ecx ; restore program header count
+49 # dec ecx
+75 EB # jnz program_header_loop
+
+58 # pop eax ; restore new process num
+
+85 ED # test ebp, ebp ; new process (vs overlay)?
+75 01 # jnz record_process_address
+48 # dec eax ; overlay
+
+#:record_process_address
+C1 E0 0C # shl eax, 0x0C
+05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &pproc_descriptor[current_process_num]
+
+03 5B 1C # add ebx, [ebx + 0x1C] ; calc first program header address
+8B 5B 08 # mov ebx, [ebx + 0x8] ; get first segment memory address
+89 18 # mov [eax], ebx ; pproc_descriptor->process_address = first segment address
+
+# setup brk
+81 C7 00 00 02 00 # add edi, 0x00020000 ; brk after last segment plus 0x20000
+89 78 04 # mov [eax + 4], edi ; pproc_descriptor->brk
+31 FF # xor edi, edi
+89 78 10 # mov [eax + 0x10], edi ; pproc->forked = false
+
+# clear open file descriptors
+89 C7 # mov edi, eax
+81 C7 00 02 00 00 # add edi, 0x0000200
+31 C0 # xor eax, eax
+B9 00 0E 00 00 # mov ecx, 0x00000E00
+F3 AA # rep stosb
+
+85 ED # test ebp, ebp ; new process (vs overlay)?
+74 06 # jz after_new_process
+
+# prepare for next process
+FF 05 1A 85 00 00 # inc [next_process_num]
+
+#:after_new_process
+# get entry point and jump
+52 # push edx
+31 C0 # xor eax, eax
+31 DB # xor ebx, ebx
+31 C9 # xor ecx, ecx
+31 D2 # xor edx, edx
+31 F6 # xor esi, esi
+31 FF # xor edi, edi
+31 ED # xor ebp, ebp
+C3 # ret
+
+
+#----------------------------------------
+#[8660]
+#:handle_syscall_chdir
+56 # push esi
+57 # push edi
+
+9A 76 82 00 00 08 00 # call absolute_path
+9A 13 83 00 00 08 00 # call find_file
+83 F8 FF # cmp eax, -1
+74 3F # je chdir_finish
+
+C1 E0 04 # shl eax, 04
+05 08 00 00 01 # add eax, 0x01000008 ; eax = &file_descriptor[filenum].file_length
+83 38 00 # cmp long [eax], 0
+74 07 # je chdir_ok
+
+# can't chdir to a file
+B8 FF FF FF FF # mov eax, -1
+EB 2B # jmp chdir_finish
+
+#:chdir_ok
+89 DE # mov esi, ebx
+8B 3D 1A 85 00 00 # mov edi, [&next_process_num]
+4F # dec edi = current process
+C1 E7 0C # shl edi, 0x0C
+81 C7 00 01 02 00 # add edi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
+
+AC # lodsb ; first slash
+AA # stosb
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 04 # jne chdir_loop
+31 C0 # xor eax, eax
+74 0D # je chdir_finish ; if "/" don't add slash
+
+#chdir_loop
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 FA # jne chdir_loop
+4F # dec edi
+
+#:add_slash
+B0 2F # mov al, '/'
+AA # stosb
+31 C0 # xor eax, eax
+AA # stosb
+
+#:chdir_finish
+5F # pop edi
+5E # pop esi
+CB # retf
+
+
+#----------------------------------------
+#[86B7]
+#:handle_syscall_exit
+A1 1A 85 00 00 # mov eax, [&next_process_num]
+48 # dec eax = current process
+A3 1A 85 00 00 # mov [&next_process_num], eax
+48 # dec eax = parent process
+
+3C 00 # cmp al, 0
+75 07 # jne not_first
+#first process
+8B 25 08 10 02 00 # mov esp, [0x021008]
+CB # ret
+
+#not_first
+C1 E0 0C # shl eax, 0x0C
+05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
+89 58 18 # mov [eax+0x18], ebx ; save child exit code
+
+8B 38 # mov edi, [eax] ; edi = pproc_descriptor->process_address
+8B 70 1C # mov esi, [eax+0x1C] ; esi = pproc_descriptor->address_of_saved_process_memory
+8B 48 20 # mov ecx, [eax+0x20] ; ecx = pproc_descriptor->length_of_process_memory
+F3 A4 # rep movsb
+
+8B 70 24 # mov esi, [eax+0x24] ; deallocate memory for saved process
+89 35 AC 84 00 00 # mov [next_save_process_address], esi
+
+8B 60 0C # mov esp, [eax+0xc] ; restore stack pointer
+8B 70 14 # mov esi, [eax+0x14] ; restore brk pointer
+89 70 04 # mov [eax+0x4], esi
+
+8B 70 24 # mov esi, [eax+0x24] ; restore stack
+89 E7 # mov edi, esp
+8B 48 28 # mov ecx, [eax+0x28]
+F3 A4 # rep movsb
+
+# mimic syscall_fork's finish
+B8 01 00 00 00 # mov eax, 0x1 ; process number for fork
+5D # pop ebp
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+CB # ret ; go back to parent
+
+
+#----------------------------------------
+#[870B]
+#:handle_syscall_waitpid
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 18 00 02 00 # add esi, 0x00020018 ; pchild_code = &pproc_descriptor[current_process_num].child_exit_code
+8B 06 # mov eax, [esi] ; get exit code
+C1 E0 08 # shl eax, 0x08 ;
+89 01 # mov [ecx], eax ; waitval = ret << 8
+31 C0 # xor eax, eax
+CB # ret
+
+
+#----------------------------------------
+#[8725]
+#:handle_syscall_lseek
+# inputs:
+# ebx: fd
+# ecx: value
+# edx: method (0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END)
+# outputs:
+# eax: offset
+#
+56 # push esi
+
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 04 02 02 00 # add esi, 0x0020204 ; pproc_descriptor = &pproc_descriptor[current_process_num].files[0].offset
+
+83 FA 01 # cmp edx, 1
+7F 13 # jg seek_end
+7C 0A # jl seek_set
+
+#:seek_cur
+8B 04 DE # mov eax, [esi+ebx*8] ; get current_offset
+01 C8 # add eax, ecx ; current_pos += offset
+89 04 DE # mov [esi+ebx*8], eax ; set current_pos
+5E # pop esi
+CB # ret
+
+#:seek_set
+89 0C DE # mov [esi+ebx*8], ecx ; set current_pos
+89 C8 # mov eax, ecx
+5E # pop esi
+CB # ret
+
+#:seek_end
+56 # push esi
+53 # push ebx
+9A 45 83 00 00 08 00 # call fd_to_file_index
+BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
+C1 E3 04 # shl ebx, 04
+01 DE # add esi, ebx
+8B 46 08 # mov eax, [esi+0x8] ; get current_length
+01 C8 # add eax, ecx ; current_length += offset
+5B # pop ebx
+5E # pop esi
+
+89 04 DE # mov [esi+ebx*8], eax ; set current_offset
+
+5E # pop esi
+CB # ret
+
+
+#----------------------------------------
+#[876D]
+#:handle_syscall_access
+#inputs:
+# ebx: path
+# ecx: mode
+9A 76 82 00 00 08 00 # call absolute_path
+9A 13 83 00 00 08 00 # call find_file
+83 F8 FF # cmp eax, -1
+74 02 # je access_error_exit
+31 C0 # xor eax, eax
+#:access_error_exit
+CB # ret
+
+
+#----------------------------------------
+#[8783]
+#:handle_syscall_mkdir
+#inputs:
+# ebx: path
+# ecx: mode
+51 # push ecx
+B9 41 00 00 00 # mov ecx, 0x41 (O_CREAT | O_WRONLY)
+9A 94 81 00 00 08 00 # call handle_syscall_open
+83 F8 FF # cmp eax, -1
+74 02 # je open_error_exit
+31 C0 # xor eax, eax
+#:open_error_exit
+59 # pop ecx
+CB # ret
+
+
+#----------------------------------------
+#[8799]
+#:handle_syscall_getcwd
+#inputs:
+# ebx: buf
+# ecx: buf size
+#outputs:
+# eax: buf
+56 # push esi
+57 # push edi
+
+89 DF # mov edi, ebx
+8B 35 1A 85 00 00 # mov esi, [&next_process_num]
+4E # dec esi = current process
+C1 E6 0C # shl esi, 0x0C
+81 C6 00 01 02 00 # add esi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
+
+# Handle root differently because we don't strip trailing slash
+66 83 3E 2F # cmp word [esi], $002f ; is cwd == "/" ?
+75 04 # jne copy_cwd
+66 A5 # movsw ; copy "/" to buffer
+EB 0A # jmp cleanup
+
+# copy_cwd
+AC # lodsb
+AA # stosb
+3C 00 # cmp al, 0
+75 FA # jne copy_cwd
+83 EF 02 # sub edi, 2 ; strip trailing slash
+AA # stosb
+
+# cleanup
+89 D8 # mov eax, ebx
+5F # pop edi
+5E # pop esi
+CB # ret
+
+
+#------------------------------------------------------------
+#[87C6]
+#:strcmp
+# inputs:
+# esi: string1
+# edi: string2
+# outputs:
+# zero flag
+#
+50 # push eax
+53 # push ebx
+56 # push esi
+57 # push edi
+
+#:check_byte
+8A 06 # mov al, [esi]
+8A 1F # mov bl, [edi]
+38 D8 # cmp al, bl
+75 0A # jne strcmp_finish
+46 # inc esi
+47 # inc edi
+84 C0 # test al, al
+75 F2 # jnz check_byte
+84 DB # test bl, bl
+75 EE # jnz check_byte
+
+#:strcmp_finish
+5F # pop edi
+5E # pop esi
+5B # pop ebx
+58 # pop eax
+CB # ret
+
+
+#------
+#[87E1]
+#:io_char
+00
+00 # free
+
+#----------------------------------------
+#[87E3]
+#:read
+53 # push ebx
+51 # push ecx
+52 # push edx
+B8 03 00 00 00 # mov eax, 3 ; syscall=read
+B9 E1 87 00 00 # mov ecx, &io_char
+BA 01 00 00 00 # mov edx, 1
+
+CD 80 # int 80 syscall
+
+3C 00 # cmp al, 0
+74 07 # je read_finish
+
+B4 01 # mov ah, 1
+A0 E1 87 00 00 # mov al, &io_char
+
+#:read_finish
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+CB # ret
+
+
+#----------------------------------------
+#[8806]
+#:write
+50 # push eax
+53 # push ebx
+51 # push ecx
+52 # push edx
+
+A2 E1 87 00 00 # mov &io_char, al
+B8 04 00 00 00 # mov eax, 4 ; syscall=write
+B9 E1 87 00 00 # mov ecx, &io_char
+BA 01 00 00 00 # mov edx, 1 1 byte characters
+CD 80 # int 80 syscall
+
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+58 # pop eax
+CB # ret
+
+
+#------
+#[8825]
+#:string_src
+#s r c \0
+73 72 63 00
+
+#----------------------------------------
+# src: create file from stdin
+#
+# Read an integer, N, in decimal from stdin.
+# Read a space.
+# Then, read a file name to create.
+# Read a newline.
+# Then, read N bytes from stdin and write to the new file.
+#----------------------------------------
+#[8829]
+#:src
+50 # push eax
+53 # push ebx
+51 # push ecx
+52 # push edx
+56 # push esi
+57 # push edi
+
+BE 25 88 00 00 # mov esi, string_src
+9A 8F 80 00 00 08 00 # call console_puts
+
+9A E3 87 00 00 08 00 # call read 'r'
+9A E3 87 00 00 08 00 # call read 'c'
+9A E3 87 00 00 08 00 # call read ' '
+
+31 C9 # xor ecx, ecx ; line count=0
+#parse_line_count_loop:
+9A E3 87 00 00 08 00 # call read
+3C 20 # cmp al, ' '
+74 0C # je got_count
+
+6B C9 0A # imul ecx, ecx, 10 ; count = count * 10
+2C 30 # sub al, 30
+0F B6 C0 # movzx eax, al
+01 C1 # add ecx, eax ; count += digit
+
+EB E9 # jmp parse_line_count_loop
+
+#:got_count
+# clear arguments
+51 # push ecx
+31 C0 # xor eax, eax
+BA 00 00 D0 04 # mov edx, 0x04D00000
+B9 00 08 00 00 # mov ecx, 0x00000800
+
+#:src_args_zeroloop
+88 02 # mov [edx], al
+42 # inc edx
+49 # dec ecx
+75 FA # jnz src_args_zeroloop
+59 # pop ecx
+
+51 # push ecx
+B9 00 00 D0 04 # mov ecx, 0x04D00000
+#:get_filename_loop
+9A E3 87 00 00 08 00 # call read
+
+3C 0A # cmp al, '\n'
+74 05 # je got_filename
+88 01 # mov [ecx], al
+41 # inc ecx
+EB F0 # jmp get_file_name_loop
+59 # pop ecx
+
+#:got_filename
+BE 00 00 D0 04 # mov esi, 0x04D00000
+9A 8F 80 00 00 08 00 # call console_puts
+
+# open filename for write
+51 # push ecx
+BB 00 00 D0 04 # mov ebx, 0x04D00000
+B8 05 00 00 00 # mov eax, 5 ; syscall_open
+B9 41 02 00 00 # mov ecx, 0x00000241 O_TRUNC (0x200) | O_CREAT (0x40) | O_WRONLY (0x1)
+BA 80 01 00 00 # mov edx, 0x00000180 S_IRUSR (0x100) | S_IWUSR (0x80)
+CD 80 # int 80
+59 # pop ecx
+89 C2 # mov edx, eax
+
+# edx has the open file number
+
+#:readwrite_loop
+85 C9 # test ecx, ecx
+74 1C # jz src_finish
+BF 00 02 04 00 # mov edi, 0x00040200 ; scratch buffer
+57 # push edi ; save buffer address
+31 DB # xor ebx, ebx ; ebx=0=stdin
+9A E3 87 00 00 08 00 # call read
+89 D3 # mov ebx, edx ; prepare to write
+5E # pop esi ; restore buffer address to esi
+9A 06 88 00 00 08 00 # call write
+49 # dec ecx ; count--
+EB E0 # jmp read_write_loop
+
+#:src_finish
+5F # pop edi
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+58 # pop eax
+CB # ret
+
+
+
+#------
+#[88E1]
+#:hex0_str
+#h e x 0 \0
+68 65 78 30 00
+
+#------------------------------------------------------------
+#[88E6]
+#:hex0
+53 # push ebx
+56 # push esi
+57 # push edi
+
+BE E1 88 00 00 # mov esi, hex0_str
+9A 8F 80 00 00 08 00 # call console_puts
+
+# read "ex0 '
+B1 04 # mov cl, 4
+#:ex0_loop
+9A E3 87 00 00 08 00 # call read
+FE C9 # dec cl
+75 F5 # jnz ex0_loop
+
+# clear arguments
+31 C0 # xor eax, eax
+BA 00 00 D0 04 # mov edx, 0x04D00000
+B9 00 08 00 00 # mov ecx, 0x00000800
+#:hex0_args_zeroloop
+88 02 # mov [edx], al
+42 # inc edx
+49 # dec ecx
+75 FA # jnz hex0_args_zeroloop
+
+BA 00 00 D0 04 # mov edx, 0x04D00000
+#:get_file_name1_loop
+9A E3 87 00 00 08 00 # call read
+9A 6F 80 00 00 08 00 # call console_putc
+3C 20 # cmp al, ' '
+74 05 # je got_filename1
+88 02 # mov [edx], al
+42 # inc edx
+EB E9 # jmp get_file_name1_loop
+
+#:got_filename1
+BA 00 04 D0 04 # mov edx, 0x04D00400
+#:get_file_name2_loop
+9A E3 87 00 00 08 00 # call read
+9A 6F 80 00 00 08 00 # call console_putc
+3C 0A # cmp al, '\n'
+74 05 # je got_filename2
+88 02 # mov [edx], al
+42 # inc edx
+EB E9 # jmp get_file_name2_loop
+
+# open filename1 for read
+BB 00 00 D0 04 # mov ebx, 0x04D00000
+B8 05 00 00 00 # mov eax, 5 ; syscall_open
+B9 00 00 00 00 # mov ecx, 0x00000000
+CD 80 # int 80
+
+50 # push eax ; save read filenum
+
+# open filename2 for write
+BB 00 04 D0 04 # mov ebx, 0x04D00400
+B8 05 00 00 00 # mov eax, 5 ; syscall_open
+B9 41 02 00 00 # mov ecx, 0x00000241 O_TRUNC (0x200) | O_CREAT (0x40) | O_WRONLY (0x1)
+BA 80 01 00 00 # mov edx, 0x00000180 S_IRUSR (0x100) | S_IWUSR (0x80)
+CD 80 # int 80
+89 C2 # mov edx, eax
+
+59 # pop ecx ; restore read filenum
+
+# this flag is set after the first digit is seen
+31 DB # xor ebx, ebx
+
+
+#------
+#[8979]
+#:hex0_read_loop
+53 # push ebx
+89 CB # mov ebx, ecx
+9A E3 87 00 00 08 00 # call read
+5B # pop ebx
+
+84 E4 # test ah, ah
+75 04 # jnz check_command
+5F # POP_DI
+5E # POP_SI
+5B # POP_BX
+CB # RETF
+
+#:check_command
+3C 23 # cmp al, '#'
+
+74 28 # jz skip_comment
+
+3C 3B # cmp ';'
+74 24 # jz skip_comment
+
+3C 66 # cmp al, 'f'
+7F D1 # jg hex0_read_loop
+
+3C 61 # cmp al, 'a'
+7C 04 # jl maybe_upper
+
+# Handle a to f
+2C 57 # sub al, 'a'-10 == 87 = 0x57
+EB 29 # jmp maybe_store
+
+#:maybe_upper
+3C 46 # cmp al, 'F'
+7F D5 # jg hex0_read_loop
+
+3C 41 # cmp al, 'A'
+7C 04 # jl maybe_digit
+
+# Handle A to F
+2C 37 # sub al, 'A'-10 == 55 = x37
+EB 1D # jmp maybe_store
+
+#:maybe_digit
+3C 39 # cmp al, '9'
+7F C9 # jg hex0_read_loop
+
+3C 30 # cmp al, '0'
+7C C5 # jl hex0_read_loop
+
+# Handle 0 to 9
+2C 30 # sub al, '0' == x30
+EB 11 # jmp maybe_store
+
+#:skip_comment
+53 # push ebx
+89 CB # mov ebx, ecx
+9A E3 87 00 00 08 00 # call read
+5B # pop ebx
+3C 0A # cmp al, '\n'
+75 F1 # jnz skip_comment
+EB B0 # jmp hex0_read_loop
+
+# only store on second digit
+#:maybe_store
+84 DB # test bl, bl
+75 09 # jnz second_digit
+
+# If on first digit, record and keep going
+#:first_digit
+C0 E0 04 # shl al, 4
+88 C7 # mov bh, al
+FE C3 # inc bl
+EB A3 # jmp hex0_read_loop
+
+# If on second digit, store and clear state
+#:second_digit
+08 C7 # or bh, al
+88 F8 # mov al, bh
+
+53 # push ebx
+89 D3 # mov ebx, edx
+9A 06 88 00 00 08 00 # call write
+5B # pop ebx
+
+31 DB # xor bx, bx
+EA 79 89 00 00 08 00 # jmp hex0_read_loop
+
+
+#------
+#[89EE]
+#:cmd_args
+00 00 D0 04
+00 04 D0 04
+
+#------
+#[89F6]
+#:cmd_env
+00 00 00 00
+
+#------------------------------------------------------------
+#[89FA]
+#:handle_other_command
+50 # push eax
+53 # push ebx
+51 # push ecx
+52 # push edx
+56 # push esi
+
+# clear arguments
+BA 00 00 D0 04 # mov edx, 0x04D00000
+88 02 # mov [edx], al
+42 # inc edx
+31 C0 # xor eax, eax
+B9 FF 07 00 00 # mov ecx, 0x000007FF
+#other_args_zeroloop
+88 02 # mov [edx], al
+42 # inc edx
+49 # dec ecx
+75 FA # jnz other_args_zeroloop
+
+BA 01 00 D0 04 # mov edx, 0x04D00001
+#:get_program_name
+9A E3 87 00 00 08 00 # call read
+3C 20 # cmp al, ' '
+74 05 # je got_program_name
+88 02 # mov [edx], al
+42 # inc edx
+EB F0 # jmp get_program_name
+
+#got_program_name
+BA 00 04 D0 04 # mov edx, 0x04D00400
+#get_argument1_loop
+9A E3 87 00 00 08 00 # call read
+3C 0A # cmp al, '\n'
+74 05 # je got_argument1
+88 02 # mov [edx], al
+42 # inc edx
+EB F0 # jmp get_argument1_loop
+
+#:got_argument1
+BE 00 00 D0 04 # mov esi, program
+9A 8F 80 00 00 08 00 # call console_puts
+
+BE 00 04 D0 04 # mov esi, arg1
+9A 8F 80 00 00 08 00 # call console_puts
+
+BB 00 00 D0 04 # mov ebx, program_name
+B9 EE 89 00 00 # mov ecx, cmd_args
+BA F6 89 00 00 # mov edx, cmd_env
+9A 1E 85 00 00 08 00 # call handle_syscall_execve
+
+5E # pop esi
+5A # pop edx
+59 # pop ecx
+5B # pop ebx
+58 # pop eax
+CB
+
+
+#------
+#[8A72]
+#:str_build_finished
+#B u i l d f i n i s h e d . \0
+42 75 69 6C 64 20 66 69 6E 69 73 68 65 64 2E 00
+
+#------
+#[8A82]
+#:str_error_no_writes
+#E R R O R : n o h d a w r i t e s ! \0
+45 52 52 4F 52 3A 20 6E 6F 20 68 64 61 20 77 72 69 74 65 73 21 00
+
+#------
+#[8A98]
+#:str_dev_hda
+#/ d e v / h d a \0
+2F 64 65 76 2F 68 64 61 00
+
+
+#------------------------------------------------------------
+#[8AA1]
+#:internalshell
+# Start reading stdin from sector 22, cyl 0, head 2 (i.e. sector 148)
+C7 05 00 00 00 01 16 00 02 00 # mov word [0x01000000], 0x00000008
+# start at "end of sector" to trigger an initial sector read
+66 C7 05 04 00 00 01 FF 01 # mov word [0x01000004], 0x01FF
+66 C7 05 00 01 02 00 2F 00 # mov [0x00020100], 0x002F ; proc[0].cwd = "/"
+66 C7 05 00 11 02 00 2F 00 # mov [0x00021100], 0x002F ; proc[1].cwd = "/"
+
+# clear file descriptors for process 0
+BF 00 02 02 00 # mov edi, 0x00020200
+B9 00 0E 00 00 # mov ecx, 0x00000E00
+31 C0 # xor eax, eax
+F3 AA # rep stosb
+
+# read from stdin
+31 DB # xor ebx, ebx
+
+#:process_command
+9A E3 87 00 00 08 00 # call read
+3C 00 # cmp al, 0
+74 23 # je build_finished
+
+#:check_src_command
+3C 73 # cmp al, 's'
+75 09 # jne check_hex0_command
+
+#:handle_src_command
+9A 29 88 00 00 08 00 # call src
+EB E8 # jmp process_command
+
+#:check_hex0_command
+3C 68 # cmp al, 'h'
+75 09 # jne call_handle_other_command
+
+#:handle_hex0_command
+9A E6 88 00 00 08 00 # call hex0
+EB DB # jmp process_command
+
+#:call_handle_other_command
+9A FA 89 00 00 08 00 # call handle_other_command
+EB D2 # jmp process_command
+
+#:build_finished
+BE 72 8A 00 00 # mov esi, str_build_finished
+9A 8F 80 00 00 08 00 # call console_puts
+
+# copy memory file /dev/hda to the boot disk
+BB 98 8A 00 00 # mov ebx, str_dev_hda
+9A 13 83 00 00 08 00 # call find_file
+83 F8 FF # cmp eax, -1
+75 17 # jne ok_exit
+
+#:error_exit
+BE 82 8A 00 00 # mov esi, str_error_no_write
+9A 8F 80 00 00 08 00 # call console_puts
+
+# one space to flush last line
+B0 20 # mov al, 20
+9A 6F 80 00 00 08 00 # call console_putc
+EB 62 # jmp shell_reboot
+
+#:ok_exit
+# get file address to read
+C1 E0 04 # shl eax, 04
+05 00 00 00 01 # add eax, 0x01000000
+8B 70 04 # mov esi, [eax+4] ; file_address
+8B 58 08 # mov ebx, [eax+8] ; bytes_to_write = file_length
+
+# print length
+89 D8 # mov eax, ebx
+B9 04 00 00 00 # mov ecx, 4
+#:shift_loop
+C1 C8 18 # ror eax, 24
+9A 7F 80 00 00 08 00 # call console_put_hex
+49 # dec ecx
+75 F3 # jnz shift_loop
+B0 0A # mov al, 0A
+9A 6F 80 00 00 08 00 # call console_putc
+
+# set starting disk location to write
+31 C9 # xor ecx, ecx
+41 # inc ecx
+B6 00 # mov dh, 0
+
+#:sector_loop
+# copy 512 bytes from file to 16 bit buffer
+51 # push ecx ; save disk location
+BF 00 A0 00 00 # mov edi, 0x000A000
+B9 00 02 00 00 # mov ecx, 0x200
+F3 A4 # rep movsb
+59 # pop ecx
+
+# now write from 16 bit buffer
+56 # push esi ; save our location in the file
+BE 00 A0 00 00 # mov esi, 0x000A000
+B8 01 00 00 00 # mov eax, 0x0001 ; num_sectors = 1
+9A BD 80 00 00 08 00 # call write_sectors
+5E # pop esi
+81 EB 00 02 00 00 # sub ebx, 0x200 ; bytes_to_write -= 512
+7F D7 # jg sector_loop
+
+B0 20 # mov al, 20
+9A 6F 80 00 00 08 00 # call console_putc
+
+#:shell_reboot
+EA CD 80 00 00 08 00 # jmp reboot
+
+# sector padding
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/kernel-bootstrap/builder-hex0-x86.hex0 b/kernel-bootstrap/builder-hex0-x86.hex0
@@ -1,2439 +0,0 @@
-# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
-# SPDX-License-Identifier: MIT
-#
-# Builder-Hex0 is a small bootable machine image which has
-# the ability to compile hex0 code. It is also written in hex0
-# and so it can build itself if provided with its own source code.
-#
-# hex0 is a "language" for binary encoding in hexadecimal
-# with support for comments.
-
-# 16 bit Functions
-# ----------------
-# MBR_entry
-# console_putc_16
-# console_put_hex_16
-#
-# get_drive_geometry
-# next_sector
-# read_sectors_16
-# write_sectors_16
-#
-# [GDT data]
-# MBR_main
-
-# 32 bit Functions
-# ----------------
-# setup_interrupt_handlers
-# stub_interrupt_handler
-# enter_16bit_real
-# resume_32bit_mode
-#
-# console_putc
-# console_put_hex
-# console_puts
-# read_sectors
-# write_sectors
-#
-# syscall_interrupt_handler
-# handle_syscall_open
-# handle_syscall_close
-# absolute_path
-# find_file
-# fd_to_file_index
-# handle_syscall_read
-# handle_syscall_brk
-# handle_syscall_write
-# handle_syscall_fork
-# handle_syscall_execve
-# handle_syscall_chdir
-# handle_syscall_exit
-# handle_syscall_waitpid
-# handle_syscall_lseek
-# handle_syscall_access
-# handle_syscall_mkdir
-# handle_syscall_getcwd
-#
-# strcmp
-#
-# read
-# write
-# src
-# hex0
-# internalshell
-
-
-#------------------------------------------------------------
-# Memory:
-# 54000000 - BFFFFFFF files (~1812MB)
-# 30000000 - 53FFFFFF saved processes (~604MB)
-# 08048000 - 2FFFFFFF current running process (~670MB)
-# 01080000 - 08000000 32 bit stack (117MB)
-# 01000010 - 0107FFFF file descriptors (16 bytes each * 32K)
-# { unused, address, length, unused }
-# 01000000 - 0100000F stdin disk locator
-# { cylinder/sector (2 bytes), head (1 byte), unused byte,
-# offset (2 bytes), unused }
-# 201800 - FFFFFF file names 6..14335
-# 201400 - 2017FF file name 5
-# 201000 - 2013FF file name 4
-# 100000 - 200FF0 unused
-# 9FC00 - FFFFF BIOS
-# 40200 - 9FBFF scratch buffer
-# 40000 - 401FF stdin device buffer
-# 20000 - 3FFFF process descriptors ( 16 * 4096 bytes each)
-# offset len description
-# 0x000 0x004 process address
-# 0x004 0x004 brk pointer
-# 0x008 0x004 saved stack pointer (first process only)
-# 0x00C 0x004 saved stack pointer
-# 0x010 0x004 forked?
-# 0x014 0x004 saved brk pointer
-# 0x018 0x004 child exit code
-# 0x01C 0x004 address of saved process memory
-# 0x020 0x004 length of process memory
-# 0x024 0x004 address of saved process stack
-# 0x028 0x004 length of saved process stack
-# 0x02C 0x01C unused
-# 0x100 0x100 current directory
-# 0x200 x0E00 file descriptors 448 * 8 bytes each
-# { global_file_index, current_offset }
-# 10800 - 1FFFF unused
-# 10000 - 107FF interrupt table
-# A000 - A1FF sector read buffer - 16bit
-# 7C00 - 8600 code
-# 7B00 - 7BFF Saved 32 bit registers while in 16 bit mode
-# < 7B00 real mode stack
-#------------------------------------------------------------
-
-
-#------------------------------------------------------------
-#[7C00]
-#:MBR_entry
-# inputs:
-# dl: boot drive
-#
-# We cannot be sure the registers are initialized to zero so we
-# do that first. We far jump to MBR_main in order to set CS.
-31 C0 # xor ax, ax
-8E D8 # mov ds, ax
-8E C0 # mov es, ax
-8E D0 # mov ss, ax
-BC 00 7B # mov sp, 0x7B00
-FC # cld ; clear direction flag
-
-EA 26 7D 00 00 # jmp MBR_main
-
-
-#------------------------
-#[7C11]
-#:console_putc_16
-# input:
-# al: char to print
-#
-# Note: with QEMU+Seabios this does not flush the last character or
-# CRLF of a line until the first character is output on the next line
-# and that character cannot be another CRLF.
-53 # push bx
-50 # push ax
-
-# Prepare to use BIOS tty output interrupt.
-# Specify text page 00, 0 black background, 7 light grey text
-BB 00 07 # mov bx, 0x0007
-# Specify the `write character` BIOS routine
-B4 0E # mov ah, 0x0E
-
-3C 0A # cmp al, 0x0A
-75 06 # jne regular
-
-# convert LF to CR LF for BIOS output
-B0 0D # mov al, 0x0D
-CD 10 # int 0x10
-B0 0A # mov al, 0x0A
-
-#:regular
-CD 10 # int 0x10
-
-58 # pop ax
-5B # pop bx
-CB # retf
-
-
-#------------------------
-#[7C27]
-#:console_put_hex_16
-# input:
-# al: byte to print as hex
-#
-50 # push ax
-
-24 F0 # and al, 0xF0
-C0 E8 04 # shr al, 4
-3C 09 # cmp al, 9
-7F 04 # jg alpha1
-
-# numeral
-04 30 # add al, 0x30
-EB 02 # jmp print1
-
-#:alpha1
-04 37 # add al, 0x37
-
-#:print1
-9A 11 7C 00 00 # call console_putc_16
-
-58 # pop ax ; restore original al
-50 # push ax ;
-
-24 0F # and al, 0x0F
-3C 09 # cmp al, 9
-7F 04 # jg alpha2
-
-# numeral
-04 30 # add al, 0x30
-EB 02 # jmp print2
-
-#:alpha2
-04 37 # add al, 0x37
-
-#:print2
-9A 11 7C 00 00 # call console_putc_16
-
-58 # pop ax
-CB # retf
-
-
-
-#-------------
-#[7C51]
-#:boot_drive
-80
-
-#-------------
-#[7C52]
-#:max_head
-0F
-
-#-------------
-#[7C53]
-#:max_sector
-3F
-
-
-#------------------------
-#[7C54]
-#:get_drive_geometry
-# input:
-# dl: drive
-#
-06 # push es
-57 # push di
-
-# https://en.wikipedia.org/wiki/INT_13H#INT_13h_AH=08h:_Read_Drive_Parameters
-31 FF # xor di, di
-8E C7 # mov es, di
-B4 08 # mov ah, 8 ; get drive parameters
-CD 13 # int 0x13
-
-88 36 52 7C # mov [max_head], dh ; max_head
-80 E1 3F # and cl, 0x3f
-88 0E 53 7C # mov [max_sector], cl ; num_sectors
-
-5F # pop di
-07 # pop es
-CB # retf
-
-
-#------------------------
-#[7C6C]
-#:next_sector
-# inputs:
-# cx: cylinder/sector
-# dh: head
-#
-50 # PUSH_AX
-
-88 C8 # mov al, cl ; get sector number
-24 3F # and al, 0x3f
-3A 06 53 7C # cmp al, [max_sector]; if sector_num == max_sector
-74 04 # je next_head ; goto next_head
-FE C1 # inc cl ; else sector_num++;
-EB 28 # jmp next_sector_finish
-
-#:next_head
-3A 36 52 7C # cmp dh, [max_head] ; if head_num == max_head
-74 09 # je next_cylinder ; goto next_cyclinder
-FE C6 # inc dh ; else head_num++
-80 E1 C0 # and cl, 0xc0 ; sector_num = 1
-FE C1 # inc cl ;
-EB 19 # jmp next_sector_finish
-
-#:next_cylinder
-80 FD FF # cmp ch, 0xff ; if cylinder_low == 255
-74 0B # je next_cyl_high
-
-#:next_cyl_low
-30 F6 # xor dh, dh ; head_num = 0
-80 E1 C0 # and cl, 0xc0 ; sector_num = 0
-81 C1 01 01 # add cx, 0x0101 ; cylinder_low++, sector_num++
-EB 09 # jmp next_sector_finish
-
-#:next_cyl_high
-30 F6 # xor dh, dh ; head_num = 0
-81 E1 C0 00 # and cx, 0x00C0 ; cylinder_low = 0, sector_num = 0
-80 C1 41 # add cl, 0x41 ; cylinder_high++, sector_num++
-
-#:next_sector_finish
-58 # pop ax
-CB # retf
-
-
-#------------------------
-#[7CA5]
-#:read_sectors_16
-# inputs:
-# di: dest_addr
-# cx: cylinder/sector
-# dh: head
-# ax: num_sectors
-#
-# outputs:
-# di: next byte to write to
-# cx,dh: next disk sector to read from
-#
-50 # push ax
-53 # push bx
-56 # push si
-
-89 C6 # mov si, ax ; si=num_sectors
-89 FB # mov bx, di ; int 13 writes to bx
-
-#:read_one_loop
-8A 16 51 7C # mov dl, [boot_drive]
-B4 02 # mov ah, 2 ; rw mode = 02 (read)
-B0 01 # mov al, 1 ; num_sectors
-CD 13 # int 0x13
-72 F4 # jnc read_one_loop
-3C 01 # cmp al, 1
-75 F0 # jnz read_one_loop
-
-# advance and maybe continue
-9A 6C 7C 00 00 # call next_sector
-
-# we read one sector, advance
-81 C3 00 02 # add bx, 0x200
-
-4E # dec si ; num_sectors--
-75 E4 # jnz read_one_loop
-
-89 DF # mov di, bx
-
-5E # pop si
-5B # pop bx
-58 # pop ax
-CB # retf
-
-
-#------------------------
-#[7CCE]
-#:write_sectors_16
-# inputs:
-# si: source_addr
-# cx: cylinder/sector
-# dh: head
-# ax: num_sectors
-#
-# outputs:
-# si: next byte to read from
-# cx,dh: next disk sector to read from
-#
-50 # push ax
-53 # push bx
-57 # push di
-
-89 C7 # mov di, ax ; di=num_sectors
-89 F3 # mov bx, si ; int 13 reads from [bx]
-
-#:write_one_loop
-8A 16 51 7C # mov dl, [boot_drive]
-B4 03 # mov ah, 3 ; rw mode = 03 (write)
-B0 01 # mov al, 1 ; num_sectors
-CD 13 # int 0x13
-72 F4 # jnc write_one_loop
-3C 01 # cmp al, 1
-75 F0 # jnz write_one_loop
-
-# advance and maybe continue
-9A 6C 7C 00 00 # call next_sector
-
-# we write one sector, advance
-81 C3 00 02 # add bx, 0x200
-
-4F # dec di ; num_sectors--
-75 E4 # jnz write_one_loop
-
-89 DE # mov si, bx
-
-5F # pop di
-5B # pop bx
-58 # pop ax
-CB # retf
-
-
-#alignment only
-00
-
-#---------------------------------------------
-# The Global Descriptor Table for 32 bit mode.
-#---------------------------------------------
-#[7CF8]
-#:GDT_start
-00 00 00 00 00 00 00 00
-
-#:GDT_code32
-FF FF # limit 0:15
-00 00 # base 0:15
-00 # base 16:23
-9A # access byte 10011010b
- # present=1 privilege=00 type=1
- # code=1 conforming=0 readable=1 accessed=0
-CF # 11001111b
- # granularity=1 32-bit-default=1 64-bit seg=0 AVL=0
-00 #
-
-#:GDT_data32
-FF FF # limit 0:15
-00 00 # base 0:15
-00 # base 16:23
-92 # access byte 10010010b
- # present=1 privilege=00 type=1
- # code=0 conforming=0 readable=1 accessed=0
-CF # flags, limit 16:19 11001111b
- # granularity=1 32-bit-default=1 64-bit seg=0 AVL=0
-00 # base 24:31
-
-#:GDT_code16
-FF FF # limit 0:15
-00 00 # base 0:15
-00 # base 16:23
-9A # access byte 10011010b
- # present=1 privilege=00 type=1
- # code=1 conforming=0 readable=1 accessed=0
-8F # 10001111b
- # granularity=1 32-bit-default=0 64-bit seg=0 AVL=0
-00 #
-
-#:GDT_data16
-FF FF # limit 0:15
-00 00 # base 0:15
-00 # base 16:23
-92 # access byte 10010010b
- # present=1 privilege=00 type=1
- # code=0 conforming=0 readable=1 accessed=0
-8F # flags, limit 16:19 10001111b
- # granularity=1 32-bit-default=0 64-bit seg=0 AVL=0
-00 # base 24:31
-
-#------
-#[7D20]
-#:GDT_locator
-27 00 # length
-F8 7C 00 00 # GDT_start
-
-
-#------------------------
-#[7D26]
-#:MBR_main
-# inputs:
-# dl: boot_drive
-#
-# Load the kernel and jump to it
-88 16 51 7C # mov [boot_drive], dl
-9A 54 7C 00 00 # call get_drive_geometry()
-BF 00 7E # mov di, 0x7E00 ; place remaining code after MBR in memory
-B8 07 00 # mov ax, 0x0007 ; num_sectors = 7
-B9 02 00 # mov cx, 0x0002 ; cylinder = 0, sector_num = 0x02
-B6 00 # mov dh, 0 ; head = 0
-9A A5 7C 00 00 # call read_sectors_16
-
-# start 32bit mode
-B8 01 24 # mov ax,2401h # enable A20 line
-CD 15 # int 15h
-
-FA # cli
-0F 01 16 20 7D # lgdt GDT_locator
-0F 20 C0 # mov eax, cr0
-66 83 C8 01 # or eax, 0x01
-0F 22 C0 # mov cr0, eax
-EA 59 7D 08 00 # jmp setup_32bit ; sets CS
-
-#------
-#[7D59]
-#:setup_32bit
-66 B8 10 00 # mov ax, 0x0010 ; data descriptor
-8E D8 # mov ds, ax
-8E D0 # mov ss, ax
-8E C0 # mov es, ax
-8E E0 # mov fs, ax
-8E E8 # mov gs, ax
-BD 00 00 00 08 # mov ebp, 0x08000000
-89 EC # mov esp, ebp
-
-9A 7C 7D 00 00 08 00 # call setup_interrupt_handlers
-EA A1 88 00 00 08 00 # jmp internalshell
-
-
-#----------------------------------------
-#[7D7C]
-#:setup_interrupt_handlers
-53 # push ebx
-
-# handle the timer interrupt 08
-BB 40 00 01 00 # mov ebx, &interrupt_table[08]
-66 C7 03 BC 7D # mov word [ebx + 0], low_address stub_interrupt_handler
-66 C7 43 06 00 00 # mov word [ebx + 6], high_address
-66 C7 43 02 08 00 # mov word [ebx + 2], code_segment = 0x0800
-C6 43 05 8E # mov byte [ebx + 5], flags = 8E
-
-# handle int 80
-BB 00 04 01 00 # mov ebx, &interrupt_table[80]
-66 C7 03 D8 7E # mov word [ebx + 0], low_address syscall_interrupt_handler
-66 C7 43 06 00 00 # mov word [ebx + 6], high_address
-66 C7 43 02 08 00 # mov word [ebx + 2], code_segment = 0x0800
-C6 43 05 8E # mov byte [ebx + 5], flags = 8E
-
-# load the interrupt table
-FA # cli
-0F 01 1D BD 7D 00 00 # lidt IDT_locator_32
-FB # sti
-5B # pop ebx
-CB # retf
-
-
-#----------------------------------------
-#[7DBC]
-#:stub_interrupt_handler
-CF # iret
-
-
-#----------------------------------------
-#[7DBD]
-#:IDT_locator_32
-FF 07 # length
-00 00 01 00 # IDT_start
-
-# unused
-00 00
-
-
-#------------------------------------------------------------
-# 32 -> 16 -> 32 bit switching functions
-#------------------------------------------------------------
-# When switching between real mode and
-# protected, registers are stored here:
-#
-# 7B14 edx
-# 7B10
-# 7B0C
-# 7B08 eax
-# 7B04 esp
-#
-# 7B00 <- top of real mode stack
-
-#----------------------------------------
-#[7DC5]
-#:enter_16bit_real
-FA # cli
-A3 08 7B 00 00 # mov [0x7B08], eax ; preserve so we can use these locally
-89 15 14 7B 00 00 # mov [0x7B14], edx ;
-5A # pop edx ; capture return address
-89 25 04 7B 00 00 # mov [0x7B04], esp ; capture stack
-
-# The following far jump sets CS to a 16-bit protected mode selector
-# and the segment registers are also set to 16-bit protected mode selectors.
-# This is done prior to entering real mode.
-EA DF 7D 00 00 18 00 # jmp 0x18:setup_16bit
-#------
-#[7DDF]
-#:setup_16bit
-B8 20 00 # mov eax, 0x0020
-8E D0 # mov ss, eax
-8E D8 # mov ds, eax
-8E C0 # mov es, eax
-8E E8 # mov gs, eax
-8E E0 # mov fs, eax
-BC 00 7B # mov sp, 0x7B00
-0F 20 C0 # mov eax, cr0
-66 83 E0 FE # and eax, 0xfffffffe ; clear protected mode
-0F 22 C0 # mov cr0, eax
-# The following far jump sets CS to a 16-bit real mode segment
-# and the segment registers are also set to real mode segments.
-EA 00 7E 00 00 # jmp 0000:XXXX real_mode
-
-# [7DFE]
-# This is the DOS/MBR identifier at offset 510:
-55 AA
-
-#------
-#[7E00]
-#:real_mode
-B8 00 00 # mov ax, 0x0
-8E D8 # mov ds, ax
-8E E0 # mov fs, ax
-8E E8 # mov gs, ax
-8E D0 # mov ss, ax
-8E C0 # mov es, ax
-BC 00 7B # mov sp, 0x7B00
-FA # cli
-0F 01 1E 22 7E # lidt IDT_locator_16
-FB # sti
-# Using retf to set CS comes from here:
-# https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode
-# This page recommends a far jump followed by sti:
-# https://www.sudleyplace.com/pmtorm.html
-6A 00 # push 0x0000 (2 bytes!) CS to return to
-52 # push dx IP to return to
-A1 08 7B # mov ax, [0x7B08] ; restore from above
-8B 16 14 7b # mov dx, [0x7B14]
-CB # retf
-
-#------
-#[7E22]
-#:IDT_locator_16
-FF FF
-00 00 00 00
-
-
-#----------------------------------------
-#[7E28]
-#:resume_32bit_mode
-FA # cli
-A3 08 7B # mov [0x7B08], ax ; preserve, they might be return values from 16 bit
-89 16 14 7b # mov [0x7B14], dx
-5A # pop dx ; carry the return IP in dx
-58 # pop ax ; CS
-0F 01 16 20 7D # lgdt GDT_locator
-0F 20 C0 # mov eax, cr0
-66 83 C8 01 # or eax, 0x01 ; enable protected mode
-0F 22 C0 # mov cr0, eax
-EA 46 7E 08 00 # jmp restore_32bit
-#------
-#[7E46]
-#:restore_32bit
-B8 10 00 00 00 # mov eax, 0x0010 ; data descriptor
-8E D8 # mov ds, eax
-8E D0 # mov ss, eax
-8E C0 # mov es, eax
-8E E0 # mov fs, eax
-8E E8 # mov gs, eax
-8B 25 04 7B 00 00 # mov esp, [0x7B04] ; restore, (saved in enter_16bit_mode)
-9A 7C 7D 00 00 08 00 # call setup_interrupt_handlers
-52 # push edx ; setup our return location
-# These restore the 16 bit portion of these registers, which may be a
-# return value from a 16 bit function, and they also restore any previous high
-# bits that were stored by enter_16bit_mode so these registers need not be
-# saved when going to 16 bit mode and back if you want them left alone.
-A1 08 7B 00 00 # mov eax, [0x7B08] ; restore, (saved at top of this function)
-8B 15 14 7B 00 00 # mov edx, [0x7B14]
-C3 # ret
-
-
-#------------------------
-#[7E6F]
-#:console_putc
-#
-E8 51 FF FF FF # CALL enter_16bit_real, next=[7E74]
-9A 11 7C 00 00 # CALL console_putc_16(al)
-9A 28 7E 00 00 # CALL resume_32bit_mode
-CB # RETF
-
-
-#------------------------
-#[7E7F]
-#:console_put_hex
-E8 41 FF FF FF # CALL enter_16bit_real, next=[7E84]
-9A 27 7C 00 00 # CALL console_put_hex_16(al)
-9A 28 7E 00 00 # CALL resume_32bit_mode
-CB # RETF
-
-
-#------------------------
-#[7E8F]
-#:console_puts
-# inputs
-# ds:si: string to print
-#:puts_loop
-50 # push eax
-56 # push esi
-8A 06 # mov al, [esi]
-3C 00 # cmp al, 0
-74 0A # jz end_puts_loop
-9A 6F 7E 00 00 08 00 # call console_putc
-46 # inc esi
-EB F0 # jmp puts_loop
-#:end_puts_loop
-B0 0A # mov al, 0A
-9A 6F 7E 00 00 08 00 # call console_putc
-5E # pop esi
-58 # pop eax
-CB # RETF
-
-
-#------------------------
-#[7EAD]
-#:read_sectors
-# inputs:
-# di: dest_addr
-# cx: cylinder/sector
-# dh: head
-# ax: num_sectors
-#
-E8 13 FF FF FF # CALL enter_16bit_real, next=[7EB2]
-9A A5 7C 00 00 # CALL read_sectors_16
-9A 28 7E 00 00 # CALL resume_32bit_mode
-CB # RETF
-
-
-#------------------------
-#[7EBD]
-#:write_sectors
-# inputs:
-# si: source_addr
-# cx: cylinder/sector
-# dh: head
-# ax: num_sectors
-#
-E8 03 FF FF FF # CALL enter_16bit_real, next=[7EC2]
-9A CE 7C 00 00 # CALL write_sectors_16
-9A 28 7E 00 00 # CALL resume_32bit_mode
-CB # RETF
-
-#------------------------
-#[7ECD]
-#:reboot
-E8 F3 FE FF FF # call enter_16bit_real, next=[7ED2]
-FA # cli
-EA F0 FF 00 F0 # ljmp $F000:FFF0 ; reboot
-
-
-#------------------------
-#[7ED8]
-#:syscall_interrupt_handler
-#
-3C 01 # cmp al, 1
-75 08 # jne try next
-9A B7 84 00 00 08 00 # call handle_syscall_exit
-CF # iret
-
-3C 02 # cmp al, 2
-75 08 # jne try next
-9A B0 82 00 00 08 00 # call handle_syscall_fork
-CF # iret
-
-3C 03 # cmp al, 3
-75 08 # jne try next
-9A 5B 81 00 00 08 00 # call handle_syscall_read
-CF # iret
-
-3C 04 # cmp al, 4
-75 08 # jne try next
-9A 3D 82 00 00 08 00 # call handle_syscall_write
-CF # iret
-
-3C 05 # cmp al, 5
-75 08 # jne try next
-9A 94 7F 00 00 08 00 # call handle_syscall_open
-CF # iret
-
-3C 06 # cmp al, 6
-75 08 # jne try next
-9A 5E 80 00 00 08 00 # call handle_syscall_close
-CF # iret
-
-3C 07 # cmp eax, 7
-75 08 # jne try next
-9A 0B 85 00 00 08 00 # call handle_syscall_waitpid
-CF # iret
-
-3C 0B # cmp eax, B
-75 08 # jne try next
-9A 1E 83 00 00 08 00 # call handle_syscall_execve
-CF # iret
-
-3C 0C # cmp al, C
-75 08 # jne try next
-9A 60 84 00 00 08 00 # call handle_syscall_chdir
-CF # iret
-
-3C 13 # cmp al, 0x13
-75 08 # jne try next
-9A 25 85 00 00 08 00 # call handle_syscall_lseek
-CF # iret
-
-3C 2D # cmp al, 2D
-75 08 # jne try next
-9A 0E 82 00 00 08 00 # call handle_syscall_brk
-CF # iret
-
-3C 21 # cmp al, 0x21
-75 08 # jne try next
-9A 6D 85 00 00 08 00 # call handle_syscall_access
-CF # iret
-
-3C 27 # cmp al, 0x27
-75 08 # jne syscall_ok
-9A 83 85 00 00 08 00 # call handle_syscall_mkdir
-CF # iret
-
-# wait4
-3C 72 # cmp eax, 0x72
-75 05 # jne try next
-31 C0 # xor eax, eax
-89 01 # mov [ecx], eax
-CF # iret
-
-3C B7 # cmp al, 0xB7
-75 08 # jne syscall_ok
-9A 99 85 00 00 08 00 # call handle_syscall_getcwd
-CF # iret
-
-#:syscall_ok
-# return success for all unimplemented syscalls
-31 C0 # xor eax, eax
-CF # iret
-
-
-#------
-#[7F8C]
-#:next_filenum
-04 00 00 00
-
-#------
-#[7F90]
-#:next_file_address
-00 00 00 54
-
-#----------------------------------------
-#[7F94]
-#:handle_syscall_open
-# inputs:
-# ebx: filename
-# ecx: flags
-#
-53 # push ebx
-51 # push ecx
-56 # push esi
-57 # push edi
-
-9A 76 80 00 00 08 00 # call absolute_path
-
-F7 C1 40 00 00 00 # test ecx, 0x40 ; 0x40 is O_CREAT
-74 72 # jz open_read
-
-# Create new file
-
-# Exit with error if directory does not exist
-
-# Go the end of filename
-89 DE # mov esi, ebx
-#:end_loop
-AC # lodsb
-3C 00 # cmp al, 0
-75 FB # jne end_loop
-# Look in reverse for last slash
-4E # dec esi
-FD # std ; go backwards
-#:find_slash_loop
-AC # lodsb
-3C 2F # cmp al, '/'
-75 FB # jne find_slash_loop
-# If first slash at start, its root, so it exists
-FC # cld
-46 # inc esi
-39 DE # cmp esi, ebx
-74 1C # je after_dir_lookup
-# Zero out slash
-31 C0 # xor eax, eax
-89 F7 # mov edi, esi
-AA # stosb
-# Lookup directory
-9A 13 81 00 00 08 00 # call find_file ; eax=find_file(ebx)
-# Restore first char
-C6 47 FF 2F # mov byte [edi - 1], 0x2f
-83 F8 FF # cmp eax, -1
-75 07 # jne after_dir_lookup
-EA 59 80 00 00 08 00 # jmp syscall_open_finish_fail
-
-#:after_dir_lookup
-
-# copy filename to new slot
-89 DE # mov esi, ebx
-BF 00 00 20 00 # mov edi, 0x0200000
-A1 8C 7F 00 00 # mov eax, [&next_filenum]
-C1 E0 0A # shl eax, 0a
-01 C7 # add edi, eax
-B9 00 04 00 00 # mov ecx, 0x0000400
-F3 A4 # rep movsb
-
-# set address of file
-BF 00 00 00 01 # mov edi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
-A1 8C 7F 00 00 # mov eax, [&next_filenum]
-C1 E0 04 # shl eax, 04
-01 C7 # add edi, eax ; pfile_descriptor += sizeof(file_descriptor) * next_filenum
-8B 0D 90 7F 00 00 # mov ecx, [next_file_address]
-
-89 4F 04 # mov [edi+4], ecx ; pfile_descriptor->file_addr = ecx
-
-31 C0 # xor eax, eax
-89 47 08 # mov [edi+8], eax ; pfile_descriptor->length = 0
-
-A1 8C 7F 00 00 # mov eax, [next_filenum] ; return next_filenum
-FF 05 8C 7F 00 00 # inc [next_filenum]
-EB 18 # jmp syscall_open_finish
-
-#open_read
-9A 13 81 00 00 08 00 # call find_file
-83 F8 FF # cmp eax, -1
-74 34 # je syscall_open_finish_fail
-
-89 C1 # mov ecx, eax
-# set read offset to start of file
-BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
-C1 E1 04 # shl ecx, 04
-01 CE # add esi, ecx ; pfile_descriptor += sizeof(file_descriptor) * filenum
-
-#:syscall_open_finish
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 20 02 02 00 # add esi, 0x0020220 ; pproc_descriptor = &pproc_descriptor[current_process_num].open_files[4]
-
-6A 04 # push 0x04 ; start at fd=4
-59 # pop ecx
-#:find_slot_loop
-8B 1E # mov ebx, [esi] ; get file number of fd slot
-85 DB # test ebx, ebx ; is this fd slot available?
-74 06 # jz got_slot
-41 # inc ecx ; no, go to next slot
-83 C6 08 # add esi, 0x08
-EB F4 # jmp find_slot_loop
-#:got_slot
-89 06 # mov [esi], eax ; store file number in slot
-89 C8 # mov eax, ecx ; return fd
-
-31 C9 # xor ecx, ecx ; set current file offset to zero
-89 4E 04 # mov [esi+0x4], ecx
-
-#--------
-#[8059]
-#:syscall_open_finish_fail
-
-5F # pop edi
-5E # pop esi
-59 # pop ecx
-5B # pop ebx
-CB # ret
-
-
-#----------------------------------------
-#[805E]
-#:handle_syscall_close
-# inputs:
-# ebx: fd
-
-57 # push edi
-8B 3D 1A 83 00 00 # mov edi, [&next_process_num]
-4F # dec edi = current process
-C1 E7 0C # shl edi, 0x0C
-81 C7 00 02 02 00 # add edi, 0x00020200 ; edi = all_procs[current_process_num].open_files
-31 C0 # xor eax, eax
-89 04 DF # mov [edi+ebx*8], eax ; open_files[fd].global_index = 0
-5F # pop edi
-CB # ret
-
-
-#----------------------------------------
-#[8076]
-#:absolute_path
-# inputs:
-# ebx: path
-# outputs:
-# ebx: absolute path
-#
-50 # push eax
-52 # push edx
-56 # push esi
-57 # push edi
-
-BF 00 02 04 00 # mov edi, 0x00040200 ; scratch buffer
-57 # push edi
-
-# if absolute path, skip prefixing current directory
-80 3b 2f # cmp [ebx], '/'
-74 18 # je strcpy_path_arg
-
-# get cwd
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 00 01 02 00 # add esi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
-
-#:strcpy_cwd_loop
-AC # lodsb
-84 C0 # test al, al
-74 03 # jz strcpy_path_arg
-AA # stosb
-EB F8 # jmp strcpy_cwd_loop
-
-#:strcpy_path_arg
-89 DE # mov esi, ebx
-# skip leading ./
-66 81 3E 2E 2F # cmp word [esi], 0x2F2E
-75 02 # jne strcpy_path
-46 # inc esi
-46 # inc esi
-
-#:strcpy_path
-31 DB # xor ebx, ebx ; init last_char
-#:strcpy_path_loop
-AC # lodsb
-3C 2F # cmp al, '/'
-75 05 # jne ok_path_char
-80 FB 2F # cmp bl, '/'
-74 01 # je skip_extra_slash
-#:ok_path_char
-AA # stosb
-#:skip_extra_slash
-84 C0 # test al, al
-74 04 # jz maybe_strip_ending_slash
-88 C3 # mov bl, al ; save last_char
-EB ED # jmp strcpy_path_loop
-
-#:maybe_strip_ending_slash
-80 FB 2F # cmp bl, '/'
-75 05 # jne handle_dots
-31 C0 # xor eax, eax
-4F # dec edi
-4F # dec edi
-AA # stosb
-
-# handle /. and /..
-#:handle_dots
-5A # pop edx ; record first parent
-52 # push edx
-
-#:handle_dots_loop
-5E # pop esi ; get start location
-56 # push esi ; save start location
-
-## find_slash
-AC # lodsb
-3C 00 # cmp al, 0
-74 33 # je absolute_path_finish
-3C 2F # cmp al, '/'
-75 F7 # jne find_slash
-
-#:found_slash
-AC # lodsb
-# check for /. or /..
-3C 00 # cmp al, 0
-74 2A # je absolute_path_finish
-3C 2E # cmp al, '.'
-74 06 # je dot_or_dotdot
-89 F2 # mov edx, esi ; record start of parent
-4A # dec edx ; go back to slash
-4A # dec edx
-EB E8 # jmp find_slash
-#:dot_or_dotdot
-AC # lodsb
-3C 2E # cmp al, '.'
-75 0A # jne remove_slashdot
-
-#:remove_parent
-89 D7 # mov edi, edx
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 FA # jne copy
-EB D7 # jmp handle_dots_loop
-
-#:remove_slashdot
-3C 00 # cmp al, 0
-75 01 # jne not_ending_slashdot
-4E # dec esi ; go back to null
-#:not_ending_slashdot
-89 F7 # mov edi, esi
-4F # dec edi
-4F # dec edi
-#:copy_over_slashdot
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 FA # jne copy_over_slashdot
-EB C6 # jmp handle_dots_loop
-
-#:absolute_path_finish
-5B # pop ebx
-
-# restore / if necessary
-80 3B 00 # cmp byte [ebx], 0
-75 05 # jne abs_path_done
-66 C7 03 2F 00 # mov word [ebx], 0x002F
-
-#:abs_path_done
-5F # pop edi
-5E # pop esi
-5A # pop edx
-58 # pop eax
-CB
-
-
-#----------------------------------------
-#[8113]
-#:find_file
-# inputs:
-# ebx: file_name
-# outputs:
-# eax: filenum
-#
-51 # push ecx
-52 # push edx
-56 # push esi
-57 # push edi
-
-A1 8C 7F 00 00 # mov eax, [next_filenum]
-48 # dec eax
-89 DE # mov esi, ebx
-
-#:checkfile
-83 F8 03 # cmp eax, 3
-74 17 # je not_found
-89 C7 # mov edi, eax
-C1 E7 0A # shl edi, 0x0a
-81 C7 00 00 20 00 # add edi, 0x0200000
-9A C6 85 00 00 08 00 # call strcmp
-74 08 # je find_file_finish
-48 # dec eax
-EB E4 # jmp checkfile
-
-#:not_found
-B8 FF FF FF FF # mov eax, 0xffffffff
-
-#:find_file_finish
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-CB # ret
-
-
-#------------------------------------------------------------
-#[8145]
-#:fd_to_file_index
-# inputs:
-# ebx: file descriptor number
-# outputs:
-# ebx: global file index
-57 # push edi
-8B 3D 1A 83 00 00 # mov edi, [&next_process_num]
-4F # dec edi = current process
-C1 E7 0C # shl edi, 0x0C
-81 C7 00 02 02 00 # add edi, 0x00020200 ; edi = all_procs[current_process_num].open_files
-8B 1C DF # mov ebx, [edi+ebx*8]
-5F # pop edi
-CB # ret
-
-
-#------------------------------------------------------------
-#[815B]
-#:handle_syscall_read
-# inputs:
-# ecx: *return_char
-# ebx: file
-# edx: length
-#
-53 # push ebx
-51 # push ecx
-52 # push edx
-56 # push esi
-57 # push edi
-
-51 # push ecx ; we need this later to return char
-83 FB 00 # cmp ebx, 0
-75 5F # jne read_memfile
-
-# stdin disk position is stored in fd 0
-# get current position
-BB 00 00 00 01 # mov ebx, 0x01000000
-66 8B 0B # mov cx, [ebx]
-8A 73 02 # mov dh, [ebx+2]
-31 C0 # xor eax, eax
-66 8B 43 04 # mov ax, [ebx+4]
-
-#end of sector?
-66 3D ff 01 # cmp ax, 0x01ff
-74 04 # je read_next_sector
-
-#:nextchar
-66 40 # inc ax
-EB 2A # jmp getchar
-
-#:read_next_sector
-BF 00 A0 00 00 # mov edi, 0x000A000
-B8 01 00 00 00 # mov eax, 0x0001 ; num_sectors = 1
-9A AD 7E 00 00 08 00 # call read_sectors
-# save new location and offset
-66 89 0b # mov [ebx], cx
-88 73 02 # mov [ebx+2], dh
-31 C0 # xor eax, eax
-
-# move block to device buffer
-BE 00 A0 00 00 # mov esi, 0x000A000
-BF 00 00 04 00 # mov edi, 0x0040000
-B9 00 02 00 00 # mov ecx, 0x0000200
-F3 A4 # rep movsb
-
-#:getchar
-66 A3 04 00 00 01 # mov [0x01000004], ax
-59 # pop ecx
-BB 00 00 04 00 # mov ebx, 0x40000 ; device buffer
-89 C6 # mov esi, eax ; offset
-8A 04 33 # mov al, [ebx+esi+0]
-88 01 # mov [ecx], al
-B8 01 00 00 00 # mov eax, 1
-EB 43 # jmp syscall_read_finish
-
-#:read_memfile
-89 D8 # mov eax, ebx ; eax = fd
-9A 45 81 00 00 08 00 # call fd_to_file_index ; ebx = global file index
-# get pointer to global file
-BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
-C1 E3 04 # shl ebx, 04
-01 DE # add esi, ebx ; pfile_descriptor += sizeof(file_descriptor) * filenum
-
-# prepare to read
-5F # pop edi ; edi = p_dst
-8B 5E 04 # mov ebx, [esi+4] ; ebx = pfile_descriptor->file_address
-89 D9 # mov ecx, ebx ;
-03 4E 08 # add ecx, [esi+0x08] ; ecx = file_address + length
-49 # dec ecx ; ecx = last address to read
-
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 04 02 02 00 # add esi, 0x0020204
-C1 E0 03 # shl eax, 3
-01 C6 # add esi, eax ; esi = &all_procs[current_proc_num].files[eax].current_offset
-
-03 1E # add ebx, [esi] ; ebx = file_addr + current_offset
-87 F3 # xchg esi, ebx ; esi = p_src, ebx = &pproc_descriptor->offset
-31 C0 # xor eax, eax ; bytes_read = 0
-
-#:syscall_read_loop
-39 CE # cmp esi, ecx ; past the end?
-77 07 # ja syscall_read_finish
-
-A4 # movsb
-40 # inc eax ; bytes_read++
-FF 03 # inc long [ebx] ; (*pcurrent_offset)++
-4A # dec edx ; length_to_read--
-75 F5 # jnz syscall_read_loop
-
-#:syscall_read_finish
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-CB # ret
-
-
-
-#------------------------------------------------------------
-#[820E]
-#:handle_syscall_brk
-56 # push esi
-
-A1 1A 83 00 00 # mov eax, [&next_process_num]
-48 # dec eax = current process
-
-BE 00 00 02 00 # mov esi, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
-C1 E0 0C # shl eax, 0x0C
-01 C6 # add esi, eax ; pproc_descriptor += sizeof(proc_descriptor) * procnum
-
-85 DB # test ebx, ebx ; if ebx == 0, just return the current brk
-74 15 # jz get_brk
-
-# set
-# initialize memory to zero
-57 # push edi
-8B 7E 04 # mov edi, [esi+4]
-31 C0 # xor eax, eax
-#:init_loop
-39 DF # cmp edi, ebx
-74 03 # je init_done
-AA # stosb
-EB F9 # jmp init_loop
-#:init_done
-5F # pop edi
-
-89 5E 04 # mov [esi+4], ebx
-89 D8 # mov eax, ebx
-5E # pop esi
-CB # ret
-
-#:get_brk
-8B 46 04 # mov eax, [esi+4] ; pproc_descriptor->brk
-5E # pop esi
-CB # ret
-
-
-#------------------------------------------------------------
-#[823D]
-#:handle_syscall_write
-# inputs:
-# ebx: file
-# ecx: address of char to write
-# edx: num bytes to write
-51 # push ecx
-52 # push edx
-56 # push esi
-57 # push edi
-
-31 C0 # xor eax, eax ; bytes_written = 0
-
-83 FB 02 # cmp ebx, 02 ; std file?
-7F 14 # jg write_memfile
-
-# stdout,stderr -> console_out
-#:std_loop
-85 D2 # test edx, edx
-74 5B # jz syscall_write_finish
-50 # push eax ; save num_written
-8A 01 # mov al, [ecx]
-9A 6F 7E 00 00 08 00 # call console_putc
-58 # pop eax ; restore num_written
-
-40 # inc eax ; num_written++
-41 # inc ecx ; p_dst++
-4A # dec edx ; count--
-EB EC # jmp std_loop
-
-#:write_memfile
-89 CE # mov esi, ecx
-
-# use ecx as pointer to fd current offset
-8B 0D 1A 83 00 00 # mov ecx, [&next_process_num]
-49 # dec ecx = current process
-C1 E1 0C # shl ecx, 0x0C
-81 C1 04 02 02 00 # add ecx, 0x0020204
-53 # push ebx
-C1 E3 03 # shl ebx, 3
-01 D9 # add ecx, ebx ; ecx = &all_procs[current_proc_num].files[ebx].current_offset
-5B # pop ebx
-
-# lookup global file index from file descriptor
-9A 45 81 00 00 08 00 # call fd_to_file_index
-C1 E3 04 # shl ebx, 04
-81 C3 00 00 00 01 # add ebx, 0x01000000 ; pfile_descriptor += sizeof(file_descriptor) * filenum
-
-8B 7B 04 # mov edi, [ebx+4] ; edi = pfile_descriptor->file_address
-03 39 # add edi, [ecx] ; edi = file_addr + current_offset
-#:write_loop
-85 D2 # test edx, edx
-74 19 # jz syscall_write_finish
-A4 # movsb
-FF 01 # inc long [ecx] ; current_offset++
-# If current offset is past previous file length, then increase length
-50 # push eax
-8B 01 # mov eax, [ecx]
-3B 43 08 # cmp eax, [ebx+0x8]
-7E 09 # jle skip_lengthen
-FF 43 08 # inc long [ebx+0x8] ; file_length++
-FF 05 90 7F 00 00 # inc long [next_file_address]
-#:skip_lengthen
-58 # pop eax
-40 # inc eax ; num_written++
-4A # dec edx
-EB E3 # jmp write_loop
-
-#:syscall_write_finish
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-CB # ret
-
-
-#------
-#[82AC]
-#:next_save_process_address
-00 00 00 30
-
-#----------------------------------------
-#[82B0]
-#:handle_syscall_fork
-53 # push ebx
-51 # push ecx
-52 # push edx
-56 # push esi
-57 # push edi
-55 # push ebp
-
-A1 1A 83 00 00 # mov eax, [&next_process_num]
-48 # dec eax = current process
-89 C2 # mov edx, eax
-BF 00 00 02 00 # mov edi, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
-C1 E0 0C # shl eax, 0x0C
-01 C7 # add edi, eax ; pproc_descriptor += sizeof(proc_descriptor) * procnum
-
-8b 77 04 # mov esi, [edi+0x4] ; save brk pointer
-89 77 14 # mov [edi+0x14], esi
-89 E6 # mov esi, esp
-89 77 0c # mov [edi+0xC], esi ; save stack pointer so we can return again later
-FF 47 10 # inc [edi+0x10] ; fork = true
-
-A1 AC 82 00 00 # mov eax, [next_save_process_address] ; set save stack location
-89 47 24 # mov [edi+0x24], eax
-
-B9 00 00 00 08 # mov ecx, 0x08000000
-29 F1 # sub ecx, esi ; compute save stack length
-01 0D AC 82 00 00 # add [next_save_process_address], ecx
-89 4F 28 # mov [edi+0x28], ecx
-89 C7 # mov edi, eax
-F3 A4 # rep movsb ; save stack
-
-# copy current process image to storage
-89 D0 # mov eax, edx ; restore current process num
-C1 E0 0C # shl eax, 0x0C
-05 00 00 02 00 # add eax, 0x0020000
-8B 30 # mov esi, [eax] ; esi = pproc_descriptor->process_address
-
-8B 48 14 # mov ecx, [eax+0x14] ; process_length = brk - process_address
-29 F1 # sub ecx, esi
-89 78 1C # mov [eax+0x1C], edi ; save address of saved process memory
-89 48 20 # mov [eax+0x20], ecx ; save length of process memory
-01 0D AC 82 00 00 # add [next_save_process_address], ecx
-F3 A4 # rep movsb ; copy current process image to storage
-
-31 C0 # xor eax, eax ; return as child, we'll return again as parent when child exits
-5D # pop ebp
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-CB # ret
-
-
-#------
-#[831A]
-#:next_process_num
-01 00 00 00
-
-#----------------------------------------
-#[831E]
-#:handle_syscall_execve
-# inputs:
-# ebx: program_name
-# ecx: char **args
-# edx: env
-#
-
-A1 1A 83 00 00 # mov eax, [next_process_num]
-3C 01 # cmp al, 1
-75 0A # jne not_first_process
-
-# first process
-BD 00 10 02 00 # mov ebp, 0x00021000 ; ebp = &proc_descriptor[1]
-89 65 08 # mov [ebp+0x8], esp ; save original stack pointer before pushing args
-EB 23 # jmp prepare_stack
-
-# not_first_process
-# check if current process forked or not.
-# if so, create new process, if not overlay current
-48 # dec eax ; eax = current_process
-C1 E0 0C # shl eax, 0x0C
-05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
-8B 68 10 # mov ebp, [eax+0x10] ; create_new_process = pproc->forked
-85 ED # test ebp, ebp ; did current process fork?
-75 0B # jnz forked
-
-#not_forked
-8B 60 0C # mov esp, [eax+0xC] ; no fork so reset initial stack to same as current process
-A1 1A 83 00 00 # mov eax, [next_process_num]
-48 # dec eax
-EB 08 # jump prepare_stack
-
-#:forked
-FF 48 10 # dec [eax+0x10] ; fork handled so reset: fork = false
-A1 1A 83 00 00 # mov eax, [next_process_num]
-
-
-#:prepare_stack
-# eax=process number to use
-# --- env ---
-8B 3D AC 82 00 00 # mov edi, [next_save_process_address]
-6A 00 # push 0 ; push end of env
-#:push_env_loop
-# copy env arg to memory for this process
-8B 32 # mov esi, [edx]
-85 F6 # test esi, esi
-74 0F # jz end_env_loop
-57 # push edi ; push p_arg
-51 # push ecx
-B9 00 01 00 00 # mov ecx, 0x00000100 ; memory per arg
-F3 A4 # rep movsb ; copy to new memory
-59 # pop ecx
-83 C2 04 # add edx, 4
-EB EB # jmp push_env_loop
-
-
-#:end_env_loop
-# --- args ---
-6A 00 # push 0 ; push end of args
-# count args
-31 C0 # xor eax, eax ; passed_args = 0
-#:countloop
-83 39 00 # cmp long [ecx], 0
-74 06 # jz push_args
-40 # inc eax
-83 C1 04 # add ecx, 4
-EB F5 # jmp countloop
-
-# push_args
-89 C2 # mov edx, eax ; save eax (can't push)
-#:push_args_loop
-83 E9 04 # sub ecx, 4
-
-# copy arg to memory for this process
-8B 31 # mov esi, [ecx]
-
-57 # push edi ; push p_arg
-
-51 # push ecx
-B9 00 01 00 00 # mov ecx, 0x00000100 ; memory per arg
-F3 A4 # rep movsb
-59 # pop ecx
-48 # dec eax
-75 EE # jnz push_args_loop
-
-# finish with argc
-89 D0 # mov eax, edx ; restore eax
-50 # push eax = argc
-
-# get current process descriptor
-A1 1A 83 00 00 # mov eax, [next_process_num]
-48 # dec eax
-50 # push eax ; save current process num
-C1 E0 0C # shl eax, 0x0C
-05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[current_process_num]
-
-89 3D AC 82 00 00 # mov [next_save_process_address], edi
-
-# copy cwd from current process
-05 00 01 00 00 # add eax, 0x100
-89 C6 # mov esi, eax
-05 00 10 00 00 # add eax, 0x1000
-89 C7 # mov edi, eax
-#loop
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 FA # jne loop
-
-58 # pop eax ; restore current process num
-40 # inc eax ; eax = new process id
-
-# prepare process image in memory
-50 # push eax ; save new process id
-# get file address and length
-9A 76 80 00 00 08 00 # call absolute_path
-9A 13 81 00 00 08 00 # call find_file ; eax=find_file(ebx)
-
-# zero process memory.
-# Do this after looking up file name because that may come from process memory.
-50 # push eax
-57 # push edi
-31 C0 # xor eax, eax
-BF 00 80 04 08 # mov edi, 0x08048000
-B9 00 80 FB 26 # mov ecx, 0x26FB8000
-F3 AA # rep stosb
-5F # pop edi
-58 # pop eax
-
-C1 E0 04 # shl eax, 04 ; pfile_descriptor = sizeof(file_descriptor) * filenum
-05 00 00 00 01 # add eax, 0x01000000 ; pfile_descriptor += &file_descriptors[0]
-
-8B 40 04 # mov eax, [eax + 0x4] ; eax = pfile_descriptor->file_address
-89 C3 # mov ebx, eax ; save file address
-31 C9 # xor ecx, ecx
-66 8B 48 2C # mov cx, [eax + 0x2C] ; get number of program headers
-8B 50 18 # mov edx, [eax + 0x18] ; get process entry address
-03 40 1C # add eax, [eax + 0x1C] ; calc first program header address
-
-#:program_header_loop
-51 # push ecx ; save program header count
-8B 70 04 # mov esi, [eax + 4] ; get segment file source offset
-01 DE # add esi, ebx ; calc segment file address
-8B 78 08 # mov edi, [eax + 8] ; get segment memory destination address
-8B 48 10 # mov ecx, [eax + 0x10] ; get segment length
-F3 A4 # rep movsb
-
-83 C0 20 # add eax, 0x20 ; go to next program header
-59 # pop ecx ; restore program header count
-49 # dec ecx
-75 EB # jnz program_header_loop
-
-58 # pop eax ; restore new process num
-
-85 ED # test ebp, ebp ; new process (vs overlay)?
-75 01 # jnz record_process_address
-48 # dec eax ; overlay
-
-#:record_process_address
-C1 E0 0C # shl eax, 0x0C
-05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &pproc_descriptor[current_process_num]
-
-03 5B 1C # add ebx, [ebx + 0x1C] ; calc first program header address
-8B 5B 08 # mov ebx, [ebx + 0x8] ; get first segment memory address
-89 18 # mov [eax], ebx ; pproc_descriptor->process_address = first segment address
-
-# setup brk
-81 C7 00 00 02 00 # add edi, 0x00020000 ; brk after last segment plus 0x20000
-89 78 04 # mov [eax + 4], edi ; pproc_descriptor->brk
-31 FF # xor edi, edi
-89 78 10 # mov [eax + 0x10], edi ; pproc->forked = false
-
-# clear open file descriptors
-89 C7 # mov edi, eax
-81 C7 00 02 00 00 # add edi, 0x0000200
-31 C0 # xor eax, eax
-B9 00 0E 00 00 # mov ecx, 0x00000E00
-F3 AA # rep stosb
-
-85 ED # test ebp, ebp ; new process (vs overlay)?
-74 06 # jz after_new_process
-
-# prepare for next process
-FF 05 1A 83 00 00 # inc [next_process_num]
-
-#:after_new_process
-# get entry point and jump
-52 # push edx
-31 C0 # xor eax, eax
-31 DB # xor ebx, ebx
-31 C9 # xor ecx, ecx
-31 D2 # xor edx, edx
-31 F6 # xor esi, esi
-31 FF # xor edi, edi
-31 ED # xor ebp, ebp
-C3 # ret
-
-
-#----------------------------------------
-#[8460]
-#:handle_syscall_chdir
-56 # push esi
-57 # push edi
-
-9A 76 80 00 00 08 00 # call absolute_path
-9A 13 81 00 00 08 00 # call find_file
-83 F8 FF # cmp eax, -1
-74 3F # je chdir_finish
-
-C1 E0 04 # shl eax, 04
-05 08 00 00 01 # add eax, 0x01000008 ; eax = &file_descriptor[filenum].file_length
-83 38 00 # cmp long [eax], 0
-74 07 # je chdir_ok
-
-# can't chdir to a file
-B8 FF FF FF FF # mov eax, -1
-EB 2B # jmp chdir_finish
-
-#:chdir_ok
-89 DE # mov esi, ebx
-8B 3D 1A 83 00 00 # mov edi, [&next_process_num]
-4F # dec edi = current process
-C1 E7 0C # shl edi, 0x0C
-81 C7 00 01 02 00 # add edi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
-
-AC # lodsb ; first slash
-AA # stosb
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 04 # jne chdir_loop
-31 C0 # xor eax, eax
-74 0D # je chdir_finish ; if "/" don't add slash
-
-#chdir_loop
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 FA # jne chdir_loop
-4F # dec edi
-
-#:add_slash
-B0 2F # mov al, '/'
-AA # stosb
-31 C0 # xor eax, eax
-AA # stosb
-
-#:chdir_finish
-5F # pop edi
-5E # pop esi
-CB # retf
-
-
-#----------------------------------------
-#[84B7]
-#:handle_syscall_exit
-A1 1A 83 00 00 # mov eax, [&next_process_num]
-48 # dec eax = current process
-A3 1A 83 00 00 # mov [&next_process_num], eax
-48 # dec eax = parent process
-
-3C 00 # cmp al, 0
-75 07 # jne not_first
-#first process
-8B 25 08 10 02 00 # mov esp, [0x021008]
-CB # ret
-
-#not_first
-C1 E0 0C # shl eax, 0x0C
-05 00 00 02 00 # add eax, 0x0020000 ; pproc_descriptor = &proc_descriptor[0]
-89 58 18 # mov [eax+0x18], ebx ; save child exit code
-
-8B 38 # mov edi, [eax] ; edi = pproc_descriptor->process_address
-8B 70 1C # mov esi, [eax+0x1C] ; esi = pproc_descriptor->address_of_saved_process_memory
-8B 48 20 # mov ecx, [eax+0x20] ; ecx = pproc_descriptor->length_of_process_memory
-F3 A4 # rep movsb
-
-8B 70 24 # mov esi, [eax+0x24] ; deallocate memory for saved process
-89 35 AC 82 00 00 # mov [next_save_process_address], esi
-
-8B 60 0C # mov esp, [eax+0xc] ; restore stack pointer
-8B 70 14 # mov esi, [eax+0x14] ; restore brk pointer
-89 70 04 # mov [eax+0x4], esi
-
-8B 70 24 # mov esi, [eax+0x24] ; restore stack
-89 E7 # mov edi, esp
-8B 48 28 # mov ecx, [eax+0x28]
-F3 A4 # rep movsb
-
-# mimic syscall_fork's finish
-B8 01 00 00 00 # mov eax, 0x1 ; process number for fork
-5D # pop ebp
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-CB # ret ; go back to parent
-
-
-#----------------------------------------
-#[850B]
-#:handle_syscall_waitpid
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 18 00 02 00 # add esi, 0x00020018 ; pchild_code = &pproc_descriptor[current_process_num].child_exit_code
-8B 06 # mov eax, [esi] ; get exit code
-C1 E0 08 # shl eax, 0x08 ;
-89 01 # mov [ecx], eax ; waitval = ret << 8
-31 C0 # xor eax, eax
-CB # ret
-
-
-#----------------------------------------
-#[8525]
-#:handle_syscall_lseek
-# inputs:
-# ebx: fd
-# ecx: value
-# edx: method (0=SEEK_SET, 1=SEEK_CUR, 2=SEEK_END)
-# outputs:
-# eax: offset
-#
-56 # push esi
-
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 04 02 02 00 # add esi, 0x0020204 ; pproc_descriptor = &pproc_descriptor[current_process_num].files[0].offset
-
-83 FA 01 # cmp edx, 1
-7F 13 # jg seek_end
-7C 0A # jl seek_set
-
-#:seek_cur
-8B 04 DE # mov eax, [esi+ebx*8] ; get current_offset
-01 C8 # add eax, ecx ; current_pos += offset
-89 04 DE # mov [esi+ebx*8], eax ; set current_pos
-5E # pop esi
-CB # ret
-
-#:seek_set
-89 0C DE # mov [esi+ebx*8], ecx ; set current_pos
-89 C8 # mov eax, ecx
-5E # pop esi
-CB # ret
-
-#:seek_end
-56 # push esi
-53 # push ebx
-9A 45 81 00 00 08 00 # call fd_to_file_index
-BE 00 00 00 01 # mov esi, 0x01000000 ; pfile_descriptor = &file_descriptor[0]
-C1 E3 04 # shl ebx, 04
-01 DE # add esi, ebx
-8B 46 08 # mov eax, [esi+0x8] ; get current_length
-01 C8 # add eax, ecx ; current_length += offset
-5B # pop ebx
-5E # pop esi
-
-89 04 DE # mov [esi+ebx*8], eax ; set current_offset
-
-5E # pop esi
-CB # ret
-
-
-#----------------------------------------
-#[856D]
-#:handle_syscall_access
-#inputs:
-# ebx: path
-# ecx: mode
-9A 76 80 00 00 08 00 # call absolute_path
-9A 13 81 00 00 08 00 # call find_file
-83 F8 FF # cmp eax, -1
-74 02 # je access_error_exit
-31 C0 # xor eax, eax
-#:access_error_exit
-CB # ret
-
-
-#----------------------------------------
-#[8583]
-#:handle_syscall_mkdir
-#inputs:
-# ebx: path
-# ecx: mode
-51 # push ecx
-B9 41 00 00 00 # mov ecx, 0x41 (O_CREAT | O_WRONLY)
-9A 94 7F 00 00 08 00 # call handle_syscall_open
-83 F8 FF # cmp eax, -1
-74 02 # je open_error_exit
-31 C0 # xor eax, eax
-#:open_error_exit
-59 # pop ecx
-CB # ret
-
-
-#----------------------------------------
-#[8599]
-#:handle_syscall_getcwd
-#inputs:
-# ebx: buf
-# ecx: buf size
-#outputs:
-# eax: buf
-56 # push esi
-57 # push edi
-
-89 DF # mov edi, ebx
-8B 35 1A 83 00 00 # mov esi, [&next_process_num]
-4E # dec esi = current process
-C1 E6 0C # shl esi, 0x0C
-81 C6 00 01 02 00 # add esi, 0x0020100 ; pproc_descriptor = &pproc_descriptor[current_process_num].current_dir
-
-# Handle root differently because we don't strip trailing slash
-66 83 3E 2F # cmp word [esi], $002f ; is cwd == "/" ?
-75 04 # jne copy_cwd
-66 A5 # movsw ; copy "/" to buffer
-EB 0A # jmp cleanup
-
-# copy_cwd
-AC # lodsb
-AA # stosb
-3C 00 # cmp al, 0
-75 FA # jne copy_cwd
-83 EF 02 # sub edi, 2 ; strip trailing slash
-AA # stosb
-
-# cleanup
-89 D8 # mov eax, ebx
-5F # pop edi
-5E # pop esi
-CB # ret
-
-
-#------------------------------------------------------------
-#[85C6]
-#:strcmp
-# inputs:
-# esi: string1
-# edi: string2
-# outputs:
-# zero flag
-#
-50 # push eax
-53 # push ebx
-56 # push esi
-57 # push edi
-
-#:check_byte
-8A 06 # mov al, [esi]
-8A 1F # mov bl, [edi]
-38 D8 # cmp al, bl
-75 0A # jne strcmp_finish
-46 # inc esi
-47 # inc edi
-84 C0 # test al, al
-75 F2 # jnz check_byte
-84 DB # test bl, bl
-75 EE # jnz check_byte
-
-#:strcmp_finish
-5F # pop edi
-5E # pop esi
-5B # pop ebx
-58 # pop eax
-CB # ret
-
-
-#------
-#[85E1]
-#:io_char
-00
-00 # free
-
-#----------------------------------------
-#[85E3]
-#:read
-53 # push ebx
-51 # push ecx
-52 # push edx
-B8 03 00 00 00 # mov eax, 3 ; syscall=read
-B9 E1 85 00 00 # mov ecx, &io_char
-BA 01 00 00 00 # mov edx, 1
-
-CD 80 # int 80 syscall
-
-3C 00 # cmp al, 0
-74 07 # je read_finish
-
-B4 01 # mov ah, 1
-A0 E1 85 00 00 # mov al, &io_char
-
-#:read_finish
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-CB # ret
-
-
-#----------------------------------------
-#[8606]
-#:write
-50 # push eax
-53 # push ebx
-51 # push ecx
-52 # push edx
-
-A2 E1 85 00 00 # mov &io_char, al
-B8 04 00 00 00 # mov eax, 4 ; syscall=write
-B9 E1 85 00 00 # mov ecx, &io_char
-BA 01 00 00 00 # mov edx, 1 1 byte characters
-CD 80 # int 80 syscall
-
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-58 # pop eax
-CB # ret
-
-
-#------
-#[8625]
-#:string_src
-#s r c \0
-73 72 63 00
-
-#----------------------------------------
-# src: create file from stdin
-#
-# Read an integer, N, in decimal from stdin.
-# Read a space.
-# Then, read a file name to create.
-# Read a newline.
-# Then, read N bytes from stdin and write to the new file.
-#----------------------------------------
-#[8629]
-#:src
-50 # push eax
-53 # push ebx
-51 # push ecx
-52 # push edx
-56 # push esi
-57 # push edi
-
-BE 25 86 00 00 # mov esi, string_src
-9A 8F 7E 00 00 08 00 # call console_puts
-
-9A E3 85 00 00 08 00 # call read 'r'
-9A E3 85 00 00 08 00 # call read 'c'
-9A E3 85 00 00 08 00 # call read ' '
-
-31 C9 # xor ecx, ecx ; line count=0
-#parse_line_count_loop:
-9A E3 85 00 00 08 00 # call read
-3C 20 # cmp al, ' '
-74 0C # je got_count
-
-6B C9 0A # imul ecx, ecx, 10 ; count = count * 10
-2C 30 # sub al, 30
-0F B6 C0 # movzx eax, al
-01 C1 # add ecx, eax ; count += digit
-
-EB E9 # jmp parse_line_count_loop
-
-#:got_count
-# clear arguments
-51 # push ecx
-31 C0 # xor eax, eax
-BA 00 00 D0 04 # mov edx, 0x04D00000
-B9 00 08 00 00 # mov ecx, 0x00000800
-
-#:src_args_zeroloop
-88 02 # mov [edx], al
-42 # inc edx
-49 # dec ecx
-75 FA # jnz src_args_zeroloop
-59 # pop ecx
-
-51 # push ecx
-B9 00 00 D0 04 # mov ecx, 0x04D00000
-#:get_filename_loop
-9A E3 85 00 00 08 00 # call read
-
-3C 0A # cmp al, '\n'
-74 05 # je got_filename
-88 01 # mov [ecx], al
-41 # inc ecx
-EB F0 # jmp get_file_name_loop
-59 # pop ecx
-
-#:got_filename
-BE 00 00 D0 04 # mov esi, 0x04D00000
-9A 8F 7E 00 00 08 00 # call console_puts
-
-# open filename for write
-51 # push ecx
-BB 00 00 D0 04 # mov ebx, 0x04D00000
-B8 05 00 00 00 # mov eax, 5 ; syscall_open
-B9 41 02 00 00 # mov ecx, 0x00000241 O_TRUNC (0x200) | O_CREAT (0x40) | O_WRONLY (0x1)
-BA 80 01 00 00 # mov edx, 0x00000180 S_IRUSR (0x100) | S_IWUSR (0x80)
-CD 80 # int 80
-59 # pop ecx
-89 C2 # mov edx, eax
-
-# edx has the open file number
-
-#:readwrite_loop
-85 C9 # test ecx, ecx
-74 1C # jz src_finish
-BF 00 02 04 00 # mov edi, 0x00040200 ; scratch buffer
-57 # push edi ; save buffer address
-31 DB # xor ebx, ebx ; ebx=0=stdin
-9A E3 85 00 00 08 00 # call read
-89 D3 # mov ebx, edx ; prepare to write
-5E # pop esi ; restore buffer address to esi
-9A 06 86 00 00 08 00 # call write
-49 # dec ecx ; count--
-EB E0 # jmp read_write_loop
-
-#:src_finish
-5F # pop edi
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-58 # pop eax
-CB # ret
-
-
-
-#------
-#[86E1]
-#:hex0_str
-#h e x 0 \0
-68 65 78 30 00
-
-#------------------------------------------------------------
-#[86E6]
-#:hex0
-53 # push ebx
-56 # push esi
-57 # push edi
-
-BE E1 86 00 00 # mov esi, hex0_str
-9A 8F 7E 00 00 08 00 # call console_puts
-
-# read "ex0 '
-B1 04 # mov cl, 4
-#:ex0_loop
-9A E3 85 00 00 08 00 # call read
-FE C9 # dec cl
-75 F5 # jnz ex0_loop
-
-# clear arguments
-31 C0 # xor eax, eax
-BA 00 00 D0 04 # mov edx, 0x04D00000
-B9 00 08 00 00 # mov ecx, 0x00000800
-#:hex0_args_zeroloop
-88 02 # mov [edx], al
-42 # inc edx
-49 # dec ecx
-75 FA # jnz hex0_args_zeroloop
-
-BA 00 00 D0 04 # mov edx, 0x04D00000
-#:get_file_name1_loop
-9A E3 85 00 00 08 00 # call read
-9A 6F 7E 00 00 08 00 # call console_putc
-3C 20 # cmp al, ' '
-74 05 # je got_filename1
-88 02 # mov [edx], al
-42 # inc edx
-EB E9 # jmp get_file_name1_loop
-
-#:got_filename1
-BA 00 04 D0 04 # mov edx, 0x04D00400
-#:get_file_name2_loop
-9A E3 85 00 00 08 00 # call read
-9A 6F 7E 00 00 08 00 # call console_putc
-3C 0A # cmp al, '\n'
-74 05 # je got_filename2
-88 02 # mov [edx], al
-42 # inc edx
-EB E9 # jmp get_file_name2_loop
-
-# open filename1 for read
-BB 00 00 D0 04 # mov ebx, 0x04D00000
-B8 05 00 00 00 # mov eax, 5 ; syscall_open
-B9 00 00 00 00 # mov ecx, 0x00000000
-CD 80 # int 80
-
-50 # push eax ; save read filenum
-
-# open filename2 for write
-BB 00 04 D0 04 # mov ebx, 0x04D00400
-B8 05 00 00 00 # mov eax, 5 ; syscall_open
-B9 41 02 00 00 # mov ecx, 0x00000241 O_TRUNC (0x200) | O_CREAT (0x40) | O_WRONLY (0x1)
-BA 80 01 00 00 # mov edx, 0x00000180 S_IRUSR (0x100) | S_IWUSR (0x80)
-CD 80 # int 80
-89 C2 # mov edx, eax
-
-59 # pop ecx ; restore read filenum
-
-# this flag is set after the first digit is seen
-31 DB # xor ebx, ebx
-
-
-#------
-#[8779]
-#:hex0_read_loop
-53 # push ebx
-89 CB # mov ebx, ecx
-9A E3 85 00 00 08 00 # call read
-5B # pop ebx
-
-84 e4 # test ah, ah
-75 04 # jnz check_command
-5F # POP_DI
-5E # POP_SI
-5B # POP_BX
-CB # RETF
-
-#:check_command
-3C 23 # cmp al, '#'
-
-74 28 # jz skip_comment
-
-3C 3B # cmp ';'
-74 24 # jz skip_comment
-
-3C 66 # cmp al, 'f'
-7F D1 # jg hex0_read_loop
-
-3C 61 # cmp al, 'a'
-7C 04 # jl maybe_upper
-
-# Handle a to f
-2C 57 # sub al, 'a'-10 == 87 = 0x57
-EB 29 # jmp maybe_store
-
-#:maybe_upper
-3C 46 # cmp al, 'F'
-7F D5 # jg hex0_read_loop
-
-3C 41 # cmp al, 'A'
-7C 04 # jl maybe_digit
-
-# Handle A to F
-2C 37 # sub al, 'A'-10 == 55 = x37
-EB 1D # jmp maybe_store
-
-#:maybe_digit
-3C 39 # cmp al, '9'
-7F C9 # jg hex0_read_loop
-
-3C 30 # cmp al, '0'
-7C C5 # jl hex0_read_loop
-
-# Handle 0 to 9
-2C 30 # sub al, '0' == x30
-EB 11 # jmp maybe_store
-
-#:skip_comment
-53 # push ebx
-89 CB # mov ebx, ecx
-9A E3 85 00 00 08 00 # call read
-5B # pop ebx
-3C 0A # cmp al, '\n'
-75 F1 # jnz skip_comment
-EB B0 # jmp hex0_read_loop
-
-# only store on second digit
-#:maybe_store
-84 DB # test bl, bl
-75 09 # jnz second_digit
-
-# If on first digit, record and keep going
-#:first_digit
-C0 E0 04 # shl al, 4
-88 C7 # mov bh, al
-FE C3 # inc bl
-EB A3 # jmp hex0_read_loop
-
-# If on second digit, store and clear state
-#:second_digit
-08 C7 # or bh, al
-88 F8 # mov al, bh
-
-53 # push ebx
-89 D3 # mov ebx, edx
-9A 06 86 00 00 08 00 # call write
-5B # pop ebx
-
-31 DB # xor bx, bx
-EA 79 87 00 00 08 00 # jmp hex0_read_loop
-
-
-#------
-#[87EE]
-#:cmd_args
-00 00 D0 04
-00 04 D0 04
-
-#------
-#[87F6]
-#:cmd_env
-00 00 00 00
-
-#------------------------------------------------------------
-#[87FA]
-#:handle_other_command
-50 # push eax
-53 # push ebx
-51 # push ecx
-52 # push edx
-56 # push esi
-
-# clear arguments
-BA 00 00 D0 04 # mov edx, 0x04D00000
-88 02 # mov [edx], al
-42 # inc edx
-31 C0 # xor eax, eax
-B9 FF 07 00 00 # mov ecx, 0x000007FF
-#other_args_zeroloop
-88 02 # mov [edx], al
-42 # inc edx
-49 # dec ecx
-75 FA # jnz other_args_zeroloop
-
-BA 01 00 D0 04 # mov edx, 0x04D00001
-#:get_program_name
-9A E3 85 00 00 08 00 # call read
-3C 20 # cmp al, ' '
-74 05 # je got_program_name
-88 02 # mov [edx], al
-42 # inc edx
-EB F0 # jmp get_program_name
-
-#got_program_name
-BA 00 04 D0 04 # mov edx, 0x04D00400
-#get_argument1_loop
-9A E3 85 00 00 08 00 # call read
-3C 0A # cmp al, '\n'
-74 05 # je got_argument1
-88 02 # mov [edx], al
-42 # inc edx
-EB F0 # jmp get_argument1_loop
-
-#:got_argument1
-BE 00 00 D0 04 # mov esi, program
-9A 8F 7E 00 00 08 00 # call console_puts
-
-BE 00 04 D0 04 # mov esi, arg1
-9A 8F 7E 00 00 08 00 # call console_puts
-
-BB 00 00 D0 04 # mov ebx, program_name
-B9 EE 87 00 00 # mov ecx, cmd_args
-BA F6 87 00 00 # mov edx, cmd_env
-9A 1E 83 00 00 08 00 # call handle_syscall_execve
-
-5E # pop esi
-5A # pop edx
-59 # pop ecx
-5B # pop ebx
-58 # pop eax
-CB
-
-
-#------
-#[8872]
-#:str_build_finished
-#B u i l d f i n i s h e d . \0
-42 75 69 6C 64 20 66 69 6E 69 73 68 65 64 2E 00
-
-#------
-#[8882]
-#:str_error_no_writes
-#E R R O R : n o h d a w r i t e s ! \0
-45 52 52 4F 52 3A 20 6E 6F 20 68 64 61 20 77 72 69 74 65 73 21 00
-
-#------
-#[8898]
-#:str_dev_hda
-#/ d e v / h d a \0
-2F 64 65 76 2F 68 64 61 00
-
-
-#------------------------------------------------------------
-#[88A1]
-#:internalshell
-# Start reading stdin from sector 8, cyl 0, head 0
-C7 05 00 00 00 01 08 00 00 00 # mov word [0x01000000], 0x00000008
-# start at "end of sector" to trigger an initial sector read
-66 C7 05 04 00 00 01 FF 01 # mov word [0x01000004], 0x01FF
-66 C7 05 00 01 02 00 2F 00 # mov [0x00020100], 0x002F ; proc[0].cwd = "/"
-66 C7 05 00 11 02 00 2F 00 # mov [0x00021100], 0x002F ; proc[1].cwd = "/"
-
-# clear file descriptors for process 0
-BF 00 02 02 00 # mov edi, 0x00020200
-B9 00 0E 00 00 # mov ecx, 0x00000E00
-31 C0 # xor eax, eax
-F3 AA # rep stosb
-
-# read from stdin
-31 DB # xor ebx, ebx
-
-#:process_command
-9A E3 85 00 00 08 00 # call read
-3C 00 # cmp al, 0
-74 23 # je build_finished
-
-#:check_src_command
-3C 73 # cmp al, 's'
-75 09 # jne check_hex0_command
-
-#:handle_src_command
-9A 29 86 00 00 08 00 # call src
-EB E8 # jmp process_command
-
-#:check_hex0_command
-3C 68 # cmp al, 'h'
-75 09 # jne call_handle_other_command
-
-#:handle_hex0_command
-9A E6 86 00 00 08 00 # call hex0
-EB DB # jmp process_command
-
-#:call_handle_other_command
-9A FA 87 00 00 08 00 # call handle_other_command
-EB D2 # jmp process_command
-
-#:build_finished
-BE 72 88 00 00 # mov esi, str_build_finished
-9A 8F 7E 00 00 08 00 # call console_puts
-
-# copy memory file /dev/hda to the boot disk
-BB 98 88 00 00 # mov ebx, str_dev_hda
-9A 13 81 00 00 08 00 # call find_file
-83 f8 ff # cmp eax, -1
-75 17 # jne ok_exit
-
-#:error_exit
-BE 82 88 00 00 # mov esi, str_error_no_write
-9A 8F 7E 00 00 08 00 # call console_puts
-
-# one space to flush last line
-B0 20 # mov al, 20
-9A 6F 7E 00 00 08 00 # call console_putc
-EB 62 # jmp shell_reboot
-
-#:ok_exit
-# get file address to read
-C1 E0 04 # shl eax, 04
-05 00 00 00 01 # add eax, 0x01000000
-8B 70 04 # mov esi, [eax+4] ; file_address
-8B 58 08 # mov ebx, [eax+8] ; bytes_to_write = file_length
-
-# print length
-89 D8 # mov eax, ebx
-B9 04 00 00 00 # mov ecx, 4
-#:shift_loop
-C1 C8 18 # ror eax, 24
-9A 7F 7E 00 00 08 00 # call console_put_hex
-49 # dec ecx
-75 F3 # jnz shift_loop
-B0 0A # mov al, 0A
-9A 6F 7E 00 00 08 00 # call console_putc
-
-# set starting disk location to write
-31 C9 # xor ecx, ecx
-41 # inc ecx
-B6 00 # mov dh, 0
-
-#:sector_loop
-# copy 512 bytes from file to 16 bit buffer
-51 # push ecx ; save disk location
-BF 00 A0 00 00 # mov edi, 0x000A000
-B9 00 02 00 00 # mov ecx, 0x200
-F3 A4 # rep movsb
-59 # pop ecx
-
-# now write from 16 bit buffer
-56 # push esi ; save our location in the file
-BE 00 A0 00 00 # mov esi, 0x000A000
-B8 01 00 00 00 # mov eax, 0x0001 ; num_sectors = 1
-9A BD 7E 00 00 08 00 # call write_sectors
-5E # pop esi
-81 EB 00 02 00 00 # sub ebx, 0x200 ; bytes_to_write -= 512
-7F D7 # jg sector_loop
-
-B0 20 # mov al, 20
-9A 6F 7E 00 00 08 00 # call console_putc
-
-#:shell_reboot
-EA CD 7E 00 00 08 00 # jmp reboot
-
-# sector padding
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/parts.rst b/parts.rst
@@ -11,13 +11,15 @@
bootstrap-seeds
===============
-This is where it all begins. We start with the two raw binary seeds ``hex0-seed`` and ``kaem-optional-seed``.
+This is where it all begins.
-First, we use those seeds to rebuild themselves.
+A kernel bootstrapping option is used by default at the beginning. The tiny ``builder-hex0-x86-stage1`` binary seed boots, builds and runs the ``builder-hex0-x86-stage2`` kernel. The ``builder-hex0-x86-stage1`` and ``builder-hex0-x86-stage2`` kernels are written in ``hex0``. The stage2 kernel has its own built-in shell, the ``hex0`` compiler and the ``src`` tool to load files into its memory file system. In this case the first step is to build the ``hex0-seed`` and ``kaem-optional-seed`` binaries from ``hex0`` source.
-Note that all early compilers before ``mes`` are part of `stage0-posix <https://github.com/oriansj/stage0-posix>`_.
+Note that all early shells and compilers before ``mes`` are part of `stage0-posix <https://github.com/oriansj/stage0-posix>`_.
-A kernel bootstrapping option is used by default at the beginning. ``hex0-seed`` can be used to compile the ``builder-hex0`` kernel which has its own built-in shell, the ``hex0`` compiler and the ``src`` tool to load files into its file system. ``builder-hex0`` runs stage0-posix and then builds ``mes`` and ``tcc``. It then builds and launches the `Fiwix <https://github.com/mikaku/Fiwix>` kernel which runs the build until Linux takes over.
+``builder-hex0-x86-stage2`` runs as the kernel for building the stage0-posix compilers and then ``mes`` and ``tcc``. Then the `Fiwix <https://github.com/mikaku/Fiwix>` kernel is built and launched. Then Fiwix runs the build until Linux takes over.
+
+If chroot or bwrap is specified or if a pre-existing kernel is provided then we start with the two raw binary seeds ``hex0-seed`` and ``kaem-optional-seed``. We use those seeds to rebuild themselves.
hex0
@@ -39,9 +41,16 @@ In the first steps we use initial ``hex0`` binary seed to rebuild ``kaem-optiona
``hex0`` can be approximated with: ``sed 's/[;#].*$//g' $input_file | xxd -r -p > $output_file``
-builder-hex0
-============
-By default (when kernel bootstrap is enabled), the ``builder-hex0`` kernel boots from a hard drive and loads an enormous shell script which embeds files (loaded with the ``src`` command) and the initial commands to build ``hex0-seed``, ``kaem-optional-seed``, and the command which launches stage0-posix using ``kaem-optional-seed`` and the stage0-posix launch script ``kaem.x86``. Builder-hex0 is written in hex0 and can be compiled with any one of ``hex0-seed``, ``sed``, the tiny ``builder-hex0-mini`` boot kernel or it can build itself.
+builder-hex0-x86-stage1
+=======================
+
+By default (when kernel bootstrap is enabled), the ``builder-hex0-x86-stage1`` boot loader/compiler boots from a hard drive and loads ``hex0`` source code from disk, compiles, and runs the ``builder-hex0-x86-stage2`` kernel. ``builder-hex0-x86-stage1`` is written in ``hex0`` and can be compiled with any one of ``hex0-seed``, ``sed``, or the tiny ``builder-hex0-mini`` binary.
+
+
+builder-hex0-x86-stage2
+=======================
+
+When kernel bootstrap is enabled, the ``builder-hex0-x86-stage2`` kernel loads an enormous shell script which embeds files (loaded with the ``src`` command) and the initial commands to build ``hex0-seed``, ``kaem-optional-seed``, and the command which launches stage0-posix using ``kaem-optional-seed`` and the stage0-posix launch script ``kaem.x86``.
kaem-optional
@@ -222,6 +231,12 @@ kexec-fiwix
If the kernel bootstrap option is enabled then a C program `kexec-fiwix` is compiled
and run which places the Fiwix ram drive in memory and launches the Fiwix kernel.
+kexec-linux
+===========
+
+If the kernel bootstrap option is enabled then a C program `kexec-linux` is compiled.
+This is used as part of the go_sysb step later to launch the Linux kernel.
+
make 3.82
=========
@@ -686,11 +701,6 @@ The next step is not a package, but the creation of the sysb rootfs, containing
all of the scripts for sysb (which merely move to sysc). Again, this is only
done in non-chroot mode, because sysb does not exist in chroot mode.
-musl 1.2.3
-==========
-Prior to building and booting Linux, musl is rebuilt yet again with syscalls
-``clone`` and ``set_thread_area`` enabled for Linux thread support.
-
Linux kernel 4.9.10
===================
@@ -711,6 +721,11 @@ subsequent systems, and we do not have ``modprobe``. Lastly,
the initramfs of sysb is generated in this stage, using ``gen_init_cpio`` within
the Linux kernel tree. This avoids the compilation of ``cpio`` as well.
+musl 1.2.3
+==========
+Prior to booting Linux, musl is rebuilt yet again with syscalls
+``clone`` and ``set_thread_area`` enabled for Linux thread support.
+
go_sysb
=======
diff --git a/rootfs.py b/rootfs.py
@@ -35,11 +35,12 @@ def create_configuration_file(args):
config.write(f"CHROOT_ONLY_SYSA={args.bwrap}\n")
config.write(f"UPDATE_CHECKSUMS={args.update_checksums}\n")
config.write(f"JOBS={args.cores}\n")
- config.write("DISK=sda1\n")
config.write(f"INTERNAL_CI={args.internal_ci}\n")
if (args.bare_metal or args.qemu) and not args.kernel:
+ config.write("DISK=sda\n")
config.write("KERNEL_BOOTSTRAP=True\n")
else:
+ config.write("DISK=sda1\n")
config.write("KERNEL_BOOTSTRAP=False\n")
config.write(f"BUILD_KERNELS={args.update_checksums or args.build_kernels}\n")
diff --git a/sysa.py b/sysa.py
@@ -13,7 +13,6 @@ import shutil
import tarfile
from lib.sysgeneral import SysGeneral, stage0_arch_map
-from lib.utils import run
# pylint: disable=consider-using-with
# pylint: disable=too-many-instance-attributes
@@ -113,6 +112,8 @@ class SysA(SysGeneral):
for root, _, filepaths in os.walk(dirpath):
if 'stage0-posix' in root:
continue
+ if root == os.path.join('sysc', 'distfiles'):
+ continue
with open(file_list_path, 'a', encoding="utf-8") as file_list:
for filepath in filepaths:
file_list.write(f"/{os.path.join(root, filepath)}\n")
@@ -193,12 +194,20 @@ class SysA(SysGeneral):
def create_builder_hex0_disk_image(self, image_file_name):
"""Create builder-hex0 disk image"""
- run(os.path.join('sysa', 'stage0-posix', 'src',
- 'bootstrap-seeds', 'POSIX', 'x86', 'hex0-seed'),
- os.path.join('kernel-bootstrap', 'builder-hex0-x86.hex0'),
- image_file_name)
+ shutil.copyfile(os.path.join('sysa', 'stage0-posix', 'src', 'bootstrap-seeds',
+ 'NATIVE', 'x86', 'builder-hex0-x86-stage1.img'),
+ image_file_name)
with open(image_file_name, 'ab') as image_file:
+ # Append stage2 hex0 source
+ with open(os.path.join('kernel-bootstrap', 'builder-hex0-x86-stage2.hex0'),
+ encoding="utf-8") as infile:
+ image_file.write(infile.read().encode())
+ # Pad to next sector
+ current_size = os.stat(image_file_name).st_size
+ while current_size % 512 != 0:
+ image_file.write(b'\0')
+ current_size += 1
self.append_srcfs(image_file)
current_size = os.stat(image_file_name).st_size
@@ -213,6 +222,6 @@ class SysA(SysGeneral):
# fill file with zeros up to desired size, one megabyte at a time
with open(image_file_name, 'ab') as image_file:
- while current_size < 1008 * megabyte:
+ while current_size < 16384 * megabyte:
image_file.write(b'\0' * megabyte)
current_size += megabyte
diff --git a/sysa/SHA256SUMS.pkgs b/sysa/SHA256SUMS.pkgs
@@ -40,7 +40,7 @@ d7d0a5fc9117f9b3ebd287851a48716c96a3c11991365edb8890f0e203d3b810 curl-7.88.1_1.
ed1581d1ef5d42c809a7db1c27614e0a900076e7ce08349ea4797944d41c7bc7 dhcpcd-10.0.1_0.tar.bz2
c4008ae6b168aee4120b0f3624a1875f9e413d8f0c637708b8b04a1fb5be173c diffutils-2.7_0.tar.bz2
bda6afcd3a390a34a57443269a4857ccc470129f7a557981778c145fd841cbd1 dist-3.5-236_0.tar.bz2
-c0514138e251062c9ac2ff1e432e01a541777bfd61480c77479ea55f5b75cdd1 e2fsprogs-1.45.7_0.tar.bz2
+5a5923e9dcbec079b032a349471627460f553a430c82bc9b4b6c0bd34ae97547 e2fsprogs-1.45.7_0.tar.bz2
d7b7453ad400eac1ba39f99971afdc392cb8a92c557ef5d6fd9fa2625124de4a ed-1.4_0.tar.bz2
258282c136145d8fba4d66f7e150800e7ca33e024483083a15d0dba3aeb5e86b file-5.44_0.tar.bz2
5984d3f2d5513dd04dc97619e2809d634fc7e3692f36f770e0202a61b6b2921d findutils-4.2.33_0.tar.bz2
@@ -62,6 +62,7 @@ d85cff8f9ff76533287891ec2019416fa585815e514743e5b76efd9f17f5ef5c grep-3.7_0.tar
b38422d646590600444f0ff12fee6fd738baaf471338aa67899db950d3521127 guile-3.0.9_0.tar.bz2
8d2015b87337abbf287f7a39ee4cf53514120b5d3e90a93fe7d533dcc43f14fa help2man-1.36.4_0.tar.bz2
3f06d1a7f1b1770d4550ff6316c7f06fd26e30bddad7c1b665f1fae80e409c8c kbd-1.15_0.tar.bz2
+d23886557310f7ff2c98898eac24b4fe8704b22e88d094e96ff996cf0d2635a4 kexec-linux-1.0.0_0.tar.bz2
2a661da13801028f5af98e5d9f6de417c21c90df1bcef4809caf0c2094fdd8f4 kexec-tools-2.0.22_0.tar.bz2
e89e4fc8ba4f917f4f609ba781fc13e43d31479d47a9da2ba3bc7ce5fcbbe6b3 libarchive-3.5.2_0.tar.bz2
36550df491767bb24d2ccab304ce70a3b4956e7c0c0e0c343d922fd57cdafbdd libatomic_ops-7.6.10_0.tar.bz2
diff --git a/sysa/e2fsprogs-1.45.7/e2fsprogs-1.45.7.sh b/sysa/e2fsprogs-1.45.7/e2fsprogs-1.45.7.sh
@@ -30,6 +30,7 @@ src_prepare() {
src_configure() {
./configure --prefix="${PREFIX}" \
--sbindir="${PREFIX}/bin" \
+ --disable-tls \
with_udev_rules_dir=no \
with_systemd_unit_dir=no
}
diff --git a/sysa/fiwix-1.4.0-lb1/fiwix-1.4.0-lb1.checksums b/sysa/fiwix-1.4.0-lb1/fiwix-1.4.0-lb1.checksums
@@ -1 +0,0 @@
-dd9e799311b3c505fa8efe045b969b851c60499ab41db546e5c8b545b3e19ec8 /boot/fiwix
diff --git a/sysa/fiwix-1.4.0-lb1/fiwix-1.4.0-lb1.kaem b/sysa/fiwix-1.4.0-lb1/fiwix-1.4.0-lb1.kaem
@@ -1,556 +0,0 @@
-#!/bin/sh
-# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
-# SPDX-License-Identifier: MIT
-
-set -ex
-
-# Check tarball checksums
-checksum-transcriber sources
-sha256sum -c sources.SHA256SUM
-
-# Extract
-mkdir build src
-cd src
-ungz --file ${distfiles}/${pkg}.tar.gz --output ${pkg}.tar
-cd ..
-
-cd build
-untar --file ../src/${pkg}.tar
-cd ${pkg}
-
-alias as="tcc -m32 -march=i386 -std=c89 -D__KERNEL__ -DMAX_PID_VALUE=64000000 -DCONFIG_MMAP2 -DCONFIG_64BIT_SYSCALLS -DNR_PROCS=4096 -DCHILD_MAX=4096 -DOPEN_MAX=1536 -DNR_OPENS=1536 -DINIT_PROGRAM=\"/init\" -DUTS_SYSNAME=\"Linux\" -D__VERSION__=\"tcc\" -traditional -I/sysa/fiwix-1.4.0-lb1/build/fiwix-1.4.0-lb1/include"
-
-alias cc="tcc -m32 -march=i386 -std=c89 -D__KERNEL__ -DMAX_PID_VALUE=64000000 -DCONFIG_MMAP2 -DCONFIG_64BIT_SYSCALLS -DNR_PROCS=4096 -DCHILD_MAX=4096 -DOPEN_MAX=1536 -DNR_OPENS=1536 -DINIT_PROGRAM=\"/init\" -DUTS_SYSNAME=\"Linux\" -D__VERSION__=\"tcc\" -I/sysa/fiwix-1.4.0-lb1/build/fiwix-1.4.0-lb1/include -O2 -fno-pie -fno-common -ffreestanding -Wall -Wstrict-prototypes"
-
-cd kernel
-as -c -o boot.o boot.S
-as -c -o core386.o core386.S
-cc -c -o main.o main.c
-cc -c -o init.o init.c
-cc -c -o gdt.o gdt.c
-cc -c -o idt.o idt.c
-cc -c -o syscalls.o syscalls.c
-cc -c -o pic.o pic.c
-cc -c -o pit.o pit.c
-cc -c -o irq.o irq.c
-cc -c -o traps.o traps.c
-cc -c -o cpu.o cpu.c
-cc -c -o cmos.o cmos.c
-cc -c -o timer.o timer.c
-cc -c -o sched.o sched.c
-cc -c -o sleep.o sleep.c
-cc -c -o signal.o signal.c
-cc -c -o process.o process.c
-cc -c -o multiboot.o multiboot.c
-
-cd syscalls
-cc -c -o umount.o umount.c
-cc -c -o getgid.o getgid.c
-cc -c -o getppid.o getppid.c
-cc -c -o fstatfs.o fstatfs.c
-cc -c -o getgroups.o getgroups.c
-cc -c -o fsync.o fsync.c
-cc -c -o setreuid.o setreuid.c
-cc -c -o newuname.o newuname.c
-cc -c -o fork.o fork.c
-cc -c -o setitimer.o setitimer.c
-cc -c -o fdatasync.o fdatasync.c
-cc -c -o chmod.o chmod.c
-cc -c -o mmap2.o mmap2.c
-cc -c -o msgsnd.o msgsnd.c
-cc -c -o madvise.o madvise.c
-cc -c -o exit.o exit.c
-cc -c -o readlink.o readlink.c
-cc -c -o socketcall.o socketcall.c
-cc -c -o stat64.o stat64.c
-cc -c -o readv.o readv.c
-cc -c -o sigaction.o sigaction.c
-cc -c -o fstat.o fstat.c
-cc -c -o waitpid.o waitpid.c
-cc -c -o setfsgid.o setfsgid.c
-cc -c -o chown.o chown.c
-cc -c -o flock.o flock.c
-cc -c -o uname.o uname.c
-cc -c -o lseek.o lseek.c
-cc -c -o setsid.o setsid.c
-cc -c -o settimeofday.o settimeofday.c
-cc -c -o unlink.o unlink.c
-cc -c -o sigprocmask.o sigprocmask.c
-cc -c -o ustat.o ustat.c
-cc -c -o open.o open.c
-cc -c -o sync.o sync.c
-cc -c -o iopl.o iopl.c
-cc -c -o msgget.o msgget.c
-cc -c -o pipe.o pipe.c
-cc -c -o shmdt.o shmdt.c
-cc -c -o getsid.o getsid.c
-cc -c -o setfsuid.o setfsuid.c
-cc -c -o signal.o signal.c
-cc -c -o newfstat.o newfstat.c
-cc -c -o mkdir.o mkdir.c
-cc -c -o getcwd.o getcwd.c
-cc -c -o link.o link.c
-cc -c -o msgctl.o msgctl.c
-cc -c -o sethostname.o sethostname.c
-cc -c -o semctl.o semctl.c
-cc -c -o sysinfo.o sysinfo.c
-cc -c -o setdomainname.o setdomainname.c
-cc -c -o getegid.o getegid.c
-cc -c -o personality.o personality.c
-cc -c -o setregid.o setregid.c
-cc -c -o setgid.o setgid.c
-cc -c -o lstat.o lstat.c
-cc -c -o getuid.o getuid.c
-cc -c -o llseek.o llseek.c
-cc -c -o select.o select.c
-cc -c -o ftruncate.o ftruncate.c
-cc -c -o getpgid.o getpgid.c
-cc -c -o brk.o brk.c
-cc -c -o getrusage.o getrusage.c
-cc -c -o sigsuspend.o sigsuspend.c
-cc -c -o writev.o writev.c
-cc -c -o times.o times.c
-cc -c -o ssetmask.o ssetmask.c
-cc -c -o stat.o stat.c
-cc -c -o fchdir.o fchdir.c
-cc -c -o chdir.o chdir.c
-cc -c -o setgroups.o setgroups.c
-cc -c -o newstat.o newstat.c
-cc -c -o creat.o creat.c
-cc -c -o getdents64.o getdents64.c
-cc -c -o getpid.o getpid.c
-cc -c -o read.o read.c
-cc -c -o dup.o dup.c
-cc -c -o utimes.o utimes.c
-cc -c -o semget.o semget.c
-cc -c -o mount.o mount.c
-cc -c -o rmdir.o rmdir.c
-cc -c -o setrlimit.o setrlimit.c
-cc -c -o sgetmask.o sgetmask.c
-cc -c -o pause.o pause.c
-cc -c -o utime.o utime.c
-cc -c -o statfs.o statfs.c
-cc -c -o ioperm.o ioperm.c
-cc -c -o exit_group.o exit_group.c
-cc -c -o ftime.o ftime.c
-cc -c -o truncate.o truncate.c
-cc -c -o pipe2.o pipe2.c
-cc -c -o old_mmap.o old_mmap.c
-cc -c -o olduname.o olduname.c
-cc -c -o kill.o kill.c
-cc -c -o gettimeofday.o gettimeofday.c
-cc -c -o fchmod.o fchmod.c
-cc -c -o fcntl64.o fcntl64.c
-cc -c -o mprotect.o mprotect.c
-cc -c -o getitimer.o getitimer.c
-cc -c -o old_select.o old_select.c
-cc -c -o symlink.o symlink.c
-cc -c -o mknod.o mknod.c
-cc -c -o write.o write.c
-cc -c -o rename.o rename.c
-cc -c -o shmat.o shmat.c
-cc -c -o ipc.o ipc.c
-cc -c -o lstat64.o lstat64.c
-cc -c -o access.o access.c
-cc -c -o getrlimit.o getrlimit.c
-cc -c -o sigreturn.o sigreturn.c
-cc -c -o ioctl.o ioctl.c
-cc -c -o umask.o umask.c
-cc -c -o geteuid.o geteuid.c
-cc -c -o munmap.o munmap.c
-cc -c -o alarm.o alarm.c
-cc -c -o nanosleep.o nanosleep.c
-cc -c -o close.o close.c
-cc -c -o chroot.o chroot.c
-cc -c -o ftruncate64.o ftruncate64.c
-cc -c -o msgrcv.o msgrcv.c
-cc -c -o umount2.o umount2.c
-cc -c -o time.o time.c
-cc -c -o stime.o stime.c
-cc -c -o semop.o semop.c
-cc -c -o newlstat.o newlstat.c
-cc -c -o sigpending.o sigpending.c
-cc -c -o reboot.o reboot.c
-cc -c -o setuid.o setuid.c
-cc -c -o wait4.o wait4.c
-cc -c -o chown32.o chown32.c
-cc -c -o fcntl.o fcntl.c
-cc -c -o fstat64.o fstat64.c
-cc -c -o shmctl.o shmctl.c
-cc -c -o dup2.o dup2.c
-cc -c -o setpgid.o setpgid.c
-cc -c -o getdents.o getdents.c
-cc -c -o getpgrp.o getpgrp.c
-cc -c -o fchown.o fchown.c
-cc -c -o execve.o execve.c
-cc -c -o shmget.o shmget.c
-cd ../..
-
-cd mm
-cc -c -o bios_map.o bios_map.c
-cc -c -o buddy_low.o buddy_low.c
-cc -c -o memory.o memory.c
-cc -c -o page.o page.c
-cc -c -o alloc.o alloc.c
-cc -c -o fault.o fault.c
-cc -c -o mmap.o mmap.c
-cc -c -o swapper.o swapper.c
-cd ..
-
-cd fs
-cc -c -o filesystems.o filesystems.c
-cc -c -o devices.o devices.c
-cc -c -o buffer.o buffer.c
-cc -c -o fd.o fd.c
-cc -c -o locks.o locks.c
-cc -c -o super.o super.c
-cc -c -o inode.o inode.c
-cc -c -o namei.o namei.c
-cc -c -o elf.o elf.c
-cc -c -o script.o script.c
-
-cd minix
-cc -c -o super.o super.c
-cc -c -o bitmaps.o bitmaps.c
-cc -c -o inode.o inode.c
-cc -c -o namei.o namei.c
-cc -c -o symlink.o symlink.c
-cc -c -o dir.o dir.c
-cc -c -o file.o file.c
-cc -c -o v1_inode.o v1_inode.c
-cc -c -o v2_inode.o v2_inode.c
-cd ..
-
-cd ext2
-cc -c -o inode.o inode.c
-cc -c -o super.o super.c
-cc -c -o namei.o namei.c
-cc -c -o symlink.o symlink.c
-cc -c -o dir.o dir.c
-cc -c -o file.o file.c
-cc -c -o bitmaps.o bitmaps.c
-cd ..
-
-cd pipefs
-cc -c -o super.o super.c
-cc -c -o fifo.o fifo.c
-cc -c -o pipe.o pipe.c
-cd ..
-
-cd iso9660
-cc -c -o inode.o inode.c
-cc -c -o super.o super.c
-cc -c -o namei.o namei.c
-cc -c -o dir.o dir.c
-cc -c -o file.o file.c
-cc -c -o rrip.o rrip.c
-cc -c -o symlink.o symlink.c
-cd ..
-
-cd procfs
-cc -c -o super.o super.c
-cc -c -o inode.o inode.c
-cc -c -o namei.o namei.c
-cc -c -o dir.o dir.c
-cc -c -o file.o file.c
-cc -c -o symlink.o symlink.c
-cc -c -o tree.o tree.c
-cc -c -o data.o data.c
-cd ../..
-
-cd drivers/char
-cc -c -o console.o console.c
-cc -c -o tty.o tty.c
-cc -c -o tty_queue.o tty_queue.c
-cc -c -o vt.o vt.c
-cc -c -o defkeymap.o defkeymap.c
-cc -c -o keyboard.o keyboard.c
-cc -c -o memdev.o memdev.c
-cc -c -o serial.o serial.c
-cc -c -o lp.o lp.c
-cc -c -o fb.o fb.c
-cc -c -o sysrq.o sysrq.c
-cd ..
-
-cd block
-cc -c -o dma.o dma.c
-cc -c -o floppy.o floppy.c
-cc -c -o part.o part.c
-cc -c -o ata.o ata.c
-cc -c -o ata_hd.o ata_hd.c
-cc -c -o atapi.o atapi.c
-cc -c -o atapi_cd.o atapi_cd.c
-cc -c -o ramdisk.o ramdisk.c
-cd ..
-
-cd pci
-cc -c -o pci.o pci.c
-cd ..
-
-cd video
-cc -c -o video.o video.c
-cc -c -o vgacon.o vgacon.c
-cc -c -o fbcon.o fbcon.c
-cc -c -o fonts.o fonts.c
-cc -c -o bga.o bga.c
-cd ../..
-
-cd lib
-cc -c -o ctype.o ctype.c
-cc -c -o strings.o strings.c
-cc -c -o printk.o printk.c
-cd ..
-
-mkdir /boot
-tcc -m32 -Wl,-Ttext=0xC0100000 -static -nostdlib -nostdinc \
- kernel/boot.o \
- kernel/core386.o \
- kernel/main.o kernel/init.o \
- kernel/gdt.o \
- kernel/idt.o \
- kernel/syscalls.o \
- kernel/pic.o \
- kernel/pit.o \
- kernel/irq.o \
- kernel/traps.o \
- kernel/cpu.o \
- kernel/cmos.o \
- kernel/timer.o \
- kernel/sched.o \
- kernel/sleep.o \
- kernel/signal.o \
- kernel/process.o \
- kernel/multiboot.o \
- kernel/syscalls/umount.o \
- kernel/syscalls/getgid.o \
- kernel/syscalls/getppid.o \
- kernel/syscalls/fstatfs.o \
- kernel/syscalls/getgroups.o \
- kernel/syscalls/fsync.o \
- kernel/syscalls/setreuid.o \
- kernel/syscalls/newuname.o \
- kernel/syscalls/fork.o \
- kernel/syscalls/setitimer.o \
- kernel/syscalls/fdatasync.o \
- kernel/syscalls/chmod.o \
- kernel/syscalls/mmap2.o \
- kernel/syscalls/msgsnd.o \
- kernel/syscalls/madvise.o \
- kernel/syscalls/exit.o \
- kernel/syscalls/readlink.o \
- kernel/syscalls/socketcall.o \
- kernel/syscalls/stat64.o \
- kernel/syscalls/readv.o \
- kernel/syscalls/sigaction.o \
- kernel/syscalls/fstat.o \
- kernel/syscalls/waitpid.o \
- kernel/syscalls/setfsgid.o \
- kernel/syscalls/chown.o \
- kernel/syscalls/flock.o \
- kernel/syscalls/uname.o \
- kernel/syscalls/lseek.o \
- kernel/syscalls/setsid.o \
- kernel/syscalls/settimeofday.o \
- kernel/syscalls/unlink.o \
- kernel/syscalls/sigprocmask.o \
- kernel/syscalls/ustat.o \
- kernel/syscalls/open.o \
- kernel/syscalls/sync.o \
- kernel/syscalls/iopl.o \
- kernel/syscalls/msgget.o \
- kernel/syscalls/pipe.o \
- kernel/syscalls/shmdt.o \
- kernel/syscalls/getsid.o \
- kernel/syscalls/setfsuid.o \
- kernel/syscalls/signal.o \
- kernel/syscalls/newfstat.o \
- kernel/syscalls/mkdir.o \
- kernel/syscalls/getcwd.o \
- kernel/syscalls/link.o \
- kernel/syscalls/msgctl.o \
- kernel/syscalls/sethostname.o \
- kernel/syscalls/semctl.o \
- kernel/syscalls/sysinfo.o \
- kernel/syscalls/setdomainname.o \
- kernel/syscalls/getegid.o \
- kernel/syscalls/personality.o \
- kernel/syscalls/setregid.o \
- kernel/syscalls/setgid.o \
- kernel/syscalls/lstat.o \
- kernel/syscalls/getuid.o \
- kernel/syscalls/llseek.o \
- kernel/syscalls/select.o \
- kernel/syscalls/ftruncate.o \
- kernel/syscalls/getpgid.o \
- kernel/syscalls/brk.o \
- kernel/syscalls/getrusage.o \
- kernel/syscalls/sigsuspend.o \
- kernel/syscalls/writev.o \
- kernel/syscalls/times.o \
- kernel/syscalls/ssetmask.o \
- kernel/syscalls/stat.o \
- kernel/syscalls/fchdir.o \
- kernel/syscalls/chdir.o \
- kernel/syscalls/setgroups.o \
- kernel/syscalls/newstat.o \
- kernel/syscalls/creat.o \
- kernel/syscalls/getdents64.o \
- kernel/syscalls/getpid.o \
- kernel/syscalls/read.o \
- kernel/syscalls/dup.o \
- kernel/syscalls/utimes.o \
- kernel/syscalls/semget.o \
- kernel/syscalls/mount.o \
- kernel/syscalls/rmdir.o \
- kernel/syscalls/setrlimit.o \
- kernel/syscalls/sgetmask.o \
- kernel/syscalls/pause.o \
- kernel/syscalls/utime.o \
- kernel/syscalls/statfs.o \
- kernel/syscalls/ioperm.o \
- kernel/syscalls/exit_group.o \
- kernel/syscalls/ftime.o \
- kernel/syscalls/truncate.o \
- kernel/syscalls/pipe2.o \
- kernel/syscalls/old_mmap.o \
- kernel/syscalls/olduname.o \
- kernel/syscalls/kill.o \
- kernel/syscalls/gettimeofday.o \
- kernel/syscalls/fchmod.o \
- kernel/syscalls/fcntl64.o \
- kernel/syscalls/mprotect.o \
- kernel/syscalls/getitimer.o \
- kernel/syscalls/old_select.o \
- kernel/syscalls/symlink.o \
- kernel/syscalls/mknod.o \
- kernel/syscalls/write.o \
- kernel/syscalls/rename.o \
- kernel/syscalls/shmat.o \
- kernel/syscalls/ipc.o \
- kernel/syscalls/lstat64.o \
- kernel/syscalls/access.o \
- kernel/syscalls/getrlimit.o \
- kernel/syscalls/sigreturn.o \
- kernel/syscalls/ioctl.o \
- kernel/syscalls/umask.o \
- kernel/syscalls/geteuid.o \
- kernel/syscalls/munmap.o \
- kernel/syscalls/alarm.o \
- kernel/syscalls/nanosleep.o \
- kernel/syscalls/close.o \
- kernel/syscalls/chroot.o \
- kernel/syscalls/ftruncate64.o \
- kernel/syscalls/msgrcv.o \
- kernel/syscalls/umount2.o \
- kernel/syscalls/time.o \
- kernel/syscalls/stime.o \
- kernel/syscalls/semop.o \
- kernel/syscalls/newlstat.o \
- kernel/syscalls/sigpending.o \
- kernel/syscalls/reboot.o \
- kernel/syscalls/setuid.o \
- kernel/syscalls/wait4.o \
- kernel/syscalls/chown32.o \
- kernel/syscalls/fcntl.o \
- kernel/syscalls/fstat64.o \
- kernel/syscalls/shmctl.o \
- kernel/syscalls/dup2.o \
- kernel/syscalls/setpgid.o \
- kernel/syscalls/getdents.o \
- kernel/syscalls/getpgrp.o \
- kernel/syscalls/fchown.o \
- kernel/syscalls/execve.o \
- kernel/syscalls/shmget.o \
- mm/bios_map.o \
- mm/buddy_low.o \
- mm/memory.o \
- mm/page.o \
- mm/alloc.o \
- mm/fault.o \
- mm/mmap.o \
- mm/swapper.o \
- fs/filesystems.o \
- fs/devices.o \
- fs/buffer.o \
- fs/fd.o \
- fs/locks.o \
- fs/super.o \
- fs/inode.o \
- fs/namei.o \
- fs/elf.o \
- fs/script.o \
- fs/minix/super.o \
- fs/minix/bitmaps.o \
- fs/minix/inode.o \
- fs/minix/namei.o \
- fs/minix/symlink.o \
- fs/minix/dir.o \
- fs/minix/file.o \
- fs/minix/v1_inode.o \
- fs/minix/v2_inode.o \
- fs/ext2/inode.o \
- fs/ext2/super.o \
- fs/ext2/namei.o \
- fs/ext2/symlink.o \
- fs/ext2/dir.o \
- fs/ext2/file.o \
- fs/ext2/bitmaps.o \
- fs/pipefs/super.o \
- fs/pipefs/fifo.o \
- fs/pipefs/pipe.o \
- fs/iso9660/inode.o \
- fs/iso9660/super.o \
- fs/iso9660/namei.o \
- fs/iso9660/dir.o \
- fs/iso9660/file.o \
- fs/iso9660/rrip.o \
- fs/iso9660/symlink.o \
- fs/procfs/super.o \
- fs/procfs/inode.o \
- fs/procfs/namei.o \
- fs/procfs/dir.o \
- fs/procfs/file.o \
- fs/procfs/symlink.o \
- fs/procfs/tree.o \
- fs/procfs/data.o \
- drivers/char/console.o \
- drivers/char/tty.o \
- drivers/char/tty_queue.o \
- drivers/char/vt.o \
- drivers/char/defkeymap.o \
- drivers/char/keyboard.o \
- drivers/char/memdev.o \
- drivers/char/serial.o \
- drivers/char/lp.o \
- drivers/char/fb.o \
- drivers/char/sysrq.o \
- drivers/block/dma.o \
- drivers/block/floppy.o \
- drivers/block/part.o \
- drivers/block/ata.o \
- drivers/block/ata_hd.o \
- drivers/block/atapi.o \
- drivers/block/atapi_cd.o \
- drivers/block/ramdisk.o \
- drivers/pci/pci.o \
- drivers/video/video.o \
- drivers/video/vgacon.o \
- drivers/video/fbcon.o \
- drivers/video/fonts.o \
- drivers/video/bga.o \
- lib/ctype.o \
- lib/strings.o \
- lib/printk.o \
- -o /boot/fiwix
-
-cd ../..
-
-# Checksums
-if match x${UPDATE_CHECKSUMS} xTrue; then
- sha256sum -o ${pkg}.checksums \
- /boot/fiwix
-
- cp ${pkg}.checksums ${srcdir}
-else
- sha256sum -c ${pkg}.checksums
-fi
diff --git a/sysa/fiwix-1.4.0-lb1/sources b/sysa/fiwix-1.4.0-lb1/sources
@@ -1 +0,0 @@
-https://github.com/rick-masters/Fiwix/releases/download/v1.4.0-lb1/fiwix-1.4.0-lb1.tar.gz ff57d1fbf0547a27dec4d7146eb9c17d01158ca5886de54e5b9bac2bec473ef3
diff --git a/sysa/fiwix-1.4.0-lb2/fiwix-1.4.0-lb2.checksums b/sysa/fiwix-1.4.0-lb2/fiwix-1.4.0-lb2.checksums
@@ -0,0 +1 @@
+0de298be5c0b00654ddb226c2e657d4fdd2fa0c613ffb3bb32c23c65d2257bf0 /boot/fiwix
diff --git a/sysa/fiwix-1.4.0-lb2/fiwix-1.4.0-lb2.kaem b/sysa/fiwix-1.4.0-lb2/fiwix-1.4.0-lb2.kaem
@@ -0,0 +1,560 @@
+#!/bin/sh
+# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
+# SPDX-License-Identifier: MIT
+
+set -ex
+
+# Check tarball checksums
+checksum-transcriber sources
+sha256sum -c sources.SHA256SUM
+
+# Extract
+mkdir build src
+cd src
+ungz --file ${distfiles}/${pkg}.tar.gz --output ${pkg}.tar
+cd ..
+
+cd build
+untar --file ../src/${pkg}.tar
+cd ${pkg}
+
+alias as="tcc -m32 -march=i386 -std=c89 -D__KERNEL__ -DMAX_PID_VALUE=64000000 -DCONFIG_MMAP2 -DCONFIG_64BIT_SYSCALLS -DCONFIG_KEXEC -DNR_PROCS=4096 -DCHILD_MAX=4096 -DOPEN_MAX=1536 -DNR_OPENS=1536 -DINIT_PROGRAM=\"/init\" -DUTS_SYSNAME=\"Linux\" -D__VERSION__=\"tcc\" -traditional -I/sysa/fiwix-1.4.0-lb2/build/fiwix-1.4.0-lb2/include"
+
+alias cc="tcc -m32 -march=i386 -std=c89 -D__KERNEL__ -DMAX_PID_VALUE=64000000 -DCONFIG_MMAP2 -DCONFIG_64BIT_SYSCALLS -DCONFIG_KEXEC -DNR_PROCS=4096 -DCHILD_MAX=4096 -DOPEN_MAX=1536 -DNR_OPENS=1536 -DINIT_PROGRAM=\"/init\" -DUTS_SYSNAME=\"Linux\" -D__VERSION__=\"tcc\" -I/sysa/fiwix-1.4.0-lb2/build/fiwix-1.4.0-lb2/include -O2 -fno-pie -fno-common -ffreestanding -Wall -Wstrict-prototypes"
+
+cd kernel
+as -c -o boot.o boot.S
+as -c -o core386.o core386.S
+cc -c -o main.o main.c
+cc -c -o init.o init.c
+cc -c -o gdt.o gdt.c
+cc -c -o idt.o idt.c
+cc -c -o syscalls.o syscalls.c
+cc -c -o pic.o pic.c
+cc -c -o pit.o pit.c
+cc -c -o irq.o irq.c
+cc -c -o traps.o traps.c
+cc -c -o cpu.o cpu.c
+cc -c -o cmos.o cmos.c
+cc -c -o timer.o timer.c
+cc -c -o sched.o sched.c
+cc -c -o sleep.o sleep.c
+cc -c -o signal.o signal.c
+cc -c -o process.o process.c
+cc -c -o multiboot.o multiboot.c
+cc -c -o kexec.o kexec.c
+
+cd syscalls
+cc -c -o umount.o umount.c
+cc -c -o getgid.o getgid.c
+cc -c -o getppid.o getppid.c
+cc -c -o fstatfs.o fstatfs.c
+cc -c -o getgroups.o getgroups.c
+cc -c -o fsync.o fsync.c
+cc -c -o setreuid.o setreuid.c
+cc -c -o newuname.o newuname.c
+cc -c -o fork.o fork.c
+cc -c -o setitimer.o setitimer.c
+cc -c -o fdatasync.o fdatasync.c
+cc -c -o chmod.o chmod.c
+cc -c -o mmap2.o mmap2.c
+cc -c -o msgsnd.o msgsnd.c
+cc -c -o madvise.o madvise.c
+cc -c -o exit.o exit.c
+cc -c -o readlink.o readlink.c
+cc -c -o socketcall.o socketcall.c
+cc -c -o stat64.o stat64.c
+cc -c -o readv.o readv.c
+cc -c -o sigaction.o sigaction.c
+cc -c -o fstat.o fstat.c
+cc -c -o waitpid.o waitpid.c
+cc -c -o setfsgid.o setfsgid.c
+cc -c -o chown.o chown.c
+cc -c -o flock.o flock.c
+cc -c -o uname.o uname.c
+cc -c -o lseek.o lseek.c
+cc -c -o setsid.o setsid.c
+cc -c -o settimeofday.o settimeofday.c
+cc -c -o unlink.o unlink.c
+cc -c -o sigprocmask.o sigprocmask.c
+cc -c -o ustat.o ustat.c
+cc -c -o open.o open.c
+cc -c -o sync.o sync.c
+cc -c -o iopl.o iopl.c
+cc -c -o msgget.o msgget.c
+cc -c -o pipe.o pipe.c
+cc -c -o shmdt.o shmdt.c
+cc -c -o getsid.o getsid.c
+cc -c -o setfsuid.o setfsuid.c
+cc -c -o signal.o signal.c
+cc -c -o newfstat.o newfstat.c
+cc -c -o mkdir.o mkdir.c
+cc -c -o getcwd.o getcwd.c
+cc -c -o link.o link.c
+cc -c -o msgctl.o msgctl.c
+cc -c -o sethostname.o sethostname.c
+cc -c -o semctl.o semctl.c
+cc -c -o sysinfo.o sysinfo.c
+cc -c -o setdomainname.o setdomainname.c
+cc -c -o getegid.o getegid.c
+cc -c -o personality.o personality.c
+cc -c -o setregid.o setregid.c
+cc -c -o setgid.o setgid.c
+cc -c -o lstat.o lstat.c
+cc -c -o getuid.o getuid.c
+cc -c -o llseek.o llseek.c
+cc -c -o select.o select.c
+cc -c -o ftruncate.o ftruncate.c
+cc -c -o getpgid.o getpgid.c
+cc -c -o brk.o brk.c
+cc -c -o getrusage.o getrusage.c
+cc -c -o sigsuspend.o sigsuspend.c
+cc -c -o writev.o writev.c
+cc -c -o times.o times.c
+cc -c -o ssetmask.o ssetmask.c
+cc -c -o stat.o stat.c
+cc -c -o fchdir.o fchdir.c
+cc -c -o chdir.o chdir.c
+cc -c -o setgroups.o setgroups.c
+cc -c -o newstat.o newstat.c
+cc -c -o creat.o creat.c
+cc -c -o getdents64.o getdents64.c
+cc -c -o getpid.o getpid.c
+cc -c -o read.o read.c
+cc -c -o dup.o dup.c
+cc -c -o utimes.o utimes.c
+cc -c -o semget.o semget.c
+cc -c -o mount.o mount.c
+cc -c -o rmdir.o rmdir.c
+cc -c -o setrlimit.o setrlimit.c
+cc -c -o sgetmask.o sgetmask.c
+cc -c -o pause.o pause.c
+cc -c -o utime.o utime.c
+cc -c -o statfs.o statfs.c
+cc -c -o ioperm.o ioperm.c
+cc -c -o exit_group.o exit_group.c
+cc -c -o ftime.o ftime.c
+cc -c -o truncate.o truncate.c
+cc -c -o pipe2.o pipe2.c
+cc -c -o old_mmap.o old_mmap.c
+cc -c -o olduname.o olduname.c
+cc -c -o kill.o kill.c
+cc -c -o gettimeofday.o gettimeofday.c
+cc -c -o fchmod.o fchmod.c
+cc -c -o fcntl64.o fcntl64.c
+cc -c -o mprotect.o mprotect.c
+cc -c -o getitimer.o getitimer.c
+cc -c -o old_select.o old_select.c
+cc -c -o symlink.o symlink.c
+cc -c -o mknod.o mknod.c
+cc -c -o write.o write.c
+cc -c -o rename.o rename.c
+cc -c -o shmat.o shmat.c
+cc -c -o ipc.o ipc.c
+cc -c -o lstat64.o lstat64.c
+cc -c -o access.o access.c
+cc -c -o getrlimit.o getrlimit.c
+cc -c -o sigreturn.o sigreturn.c
+cc -c -o ioctl.o ioctl.c
+cc -c -o umask.o umask.c
+cc -c -o geteuid.o geteuid.c
+cc -c -o munmap.o munmap.c
+cc -c -o alarm.o alarm.c
+cc -c -o nanosleep.o nanosleep.c
+cc -c -o close.o close.c
+cc -c -o chroot.o chroot.c
+cc -c -o ftruncate64.o ftruncate64.c
+cc -c -o msgrcv.o msgrcv.c
+cc -c -o umount2.o umount2.c
+cc -c -o time.o time.c
+cc -c -o stime.o stime.c
+cc -c -o semop.o semop.c
+cc -c -o newlstat.o newlstat.c
+cc -c -o sigpending.o sigpending.c
+cc -c -o reboot.o reboot.c
+cc -c -o setuid.o setuid.c
+cc -c -o wait4.o wait4.c
+cc -c -o chown32.o chown32.c
+cc -c -o fcntl.o fcntl.c
+cc -c -o fstat64.o fstat64.c
+cc -c -o shmctl.o shmctl.c
+cc -c -o dup2.o dup2.c
+cc -c -o setpgid.o setpgid.c
+cc -c -o getdents.o getdents.c
+cc -c -o getpgrp.o getpgrp.c
+cc -c -o fchown.o fchown.c
+cc -c -o execve.o execve.c
+cc -c -o shmget.o shmget.c
+cd ../..
+
+cd mm
+cc -c -o bios_map.o bios_map.c
+cc -c -o buddy_low.o buddy_low.c
+cc -c -o memory.o memory.c
+cc -c -o page.o page.c
+cc -c -o alloc.o alloc.c
+cc -c -o fault.o fault.c
+cc -c -o mmap.o mmap.c
+cc -c -o swapper.o swapper.c
+cd ..
+
+cd fs
+cc -c -o filesystems.o filesystems.c
+cc -c -o devices.o devices.c
+cc -c -o buffer.o buffer.c
+cc -c -o fd.o fd.c
+cc -c -o locks.o locks.c
+cc -c -o super.o super.c
+cc -c -o inode.o inode.c
+cc -c -o namei.o namei.c
+cc -c -o elf.o elf.c
+cc -c -o script.o script.c
+
+cd minix
+cc -c -o super.o super.c
+cc -c -o bitmaps.o bitmaps.c
+cc -c -o inode.o inode.c
+cc -c -o namei.o namei.c
+cc -c -o symlink.o symlink.c
+cc -c -o dir.o dir.c
+cc -c -o file.o file.c
+cc -c -o v1_inode.o v1_inode.c
+cc -c -o v2_inode.o v2_inode.c
+cd ..
+
+cd ext2
+cc -c -o inode.o inode.c
+cc -c -o super.o super.c
+cc -c -o namei.o namei.c
+cc -c -o symlink.o symlink.c
+cc -c -o dir.o dir.c
+cc -c -o file.o file.c
+cc -c -o bitmaps.o bitmaps.c
+cd ..
+
+cd pipefs
+cc -c -o super.o super.c
+cc -c -o fifo.o fifo.c
+cc -c -o pipe.o pipe.c
+cd ..
+
+cd iso9660
+cc -c -o inode.o inode.c
+cc -c -o super.o super.c
+cc -c -o namei.o namei.c
+cc -c -o dir.o dir.c
+cc -c -o file.o file.c
+cc -c -o rrip.o rrip.c
+cc -c -o symlink.o symlink.c
+cd ..
+
+cd procfs
+cc -c -o super.o super.c
+cc -c -o inode.o inode.c
+cc -c -o namei.o namei.c
+cc -c -o dir.o dir.c
+cc -c -o file.o file.c
+cc -c -o symlink.o symlink.c
+cc -c -o tree.o tree.c
+cc -c -o data.o data.c
+cd ../..
+
+cd drivers/char
+cc -c -o console.o console.c
+cc -c -o tty.o tty.c
+cc -c -o tty_queue.o tty_queue.c
+cc -c -o vt.o vt.c
+cc -c -o defkeymap.o defkeymap.c
+cc -c -o keyboard.o keyboard.c
+cc -c -o memdev.o memdev.c
+cc -c -o serial.o serial.c
+cc -c -o lp.o lp.c
+cc -c -o fb.o fb.c
+cc -c -o sysrq.o sysrq.c
+cd ..
+
+cd block
+cc -c -o dma.o dma.c
+cc -c -o floppy.o floppy.c
+cc -c -o part.o part.c
+cc -c -o ata.o ata.c
+cc -c -o ata_hd.o ata_hd.c
+cc -c -o ata_pci.o ata_pci.c
+cc -c -o atapi.o atapi.c
+cc -c -o atapi_cd.o atapi_cd.c
+cc -c -o ramdisk.o ramdisk.c
+cd ..
+
+cd pci
+cc -c -o pci.o pci.c
+cd ..
+
+cd video
+cc -c -o video.o video.c
+cc -c -o vgacon.o vgacon.c
+cc -c -o fbcon.o fbcon.c
+cc -c -o fonts.o fonts.c
+cc -c -o bga.o bga.c
+cd ../..
+
+cd lib
+cc -c -o ctype.o ctype.c
+cc -c -o strings.o strings.c
+cc -c -o printk.o printk.c
+cd ..
+
+mkdir /boot
+tcc -m32 -Wl,-Ttext=0xC0100000 -static -nostdlib -nostdinc \
+ kernel/boot.o \
+ kernel/core386.o \
+ kernel/main.o kernel/init.o \
+ kernel/gdt.o \
+ kernel/idt.o \
+ kernel/syscalls.o \
+ kernel/pic.o \
+ kernel/pit.o \
+ kernel/irq.o \
+ kernel/traps.o \
+ kernel/cpu.o \
+ kernel/cmos.o \
+ kernel/timer.o \
+ kernel/sched.o \
+ kernel/sleep.o \
+ kernel/signal.o \
+ kernel/process.o \
+ kernel/multiboot.o \
+ kernel/kexec.o \
+ kernel/syscalls/umount.o \
+ kernel/syscalls/getgid.o \
+ kernel/syscalls/getppid.o \
+ kernel/syscalls/fstatfs.o \
+ kernel/syscalls/getgroups.o \
+ kernel/syscalls/fsync.o \
+ kernel/syscalls/setreuid.o \
+ kernel/syscalls/newuname.o \
+ kernel/syscalls/fork.o \
+ kernel/syscalls/setitimer.o \
+ kernel/syscalls/fdatasync.o \
+ kernel/syscalls/chmod.o \
+ kernel/syscalls/mmap2.o \
+ kernel/syscalls/msgsnd.o \
+ kernel/syscalls/madvise.o \
+ kernel/syscalls/exit.o \
+ kernel/syscalls/readlink.o \
+ kernel/syscalls/socketcall.o \
+ kernel/syscalls/stat64.o \
+ kernel/syscalls/readv.o \
+ kernel/syscalls/sigaction.o \
+ kernel/syscalls/fstat.o \
+ kernel/syscalls/waitpid.o \
+ kernel/syscalls/setfsgid.o \
+ kernel/syscalls/chown.o \
+ kernel/syscalls/flock.o \
+ kernel/syscalls/uname.o \
+ kernel/syscalls/lseek.o \
+ kernel/syscalls/setsid.o \
+ kernel/syscalls/settimeofday.o \
+ kernel/syscalls/unlink.o \
+ kernel/syscalls/sigprocmask.o \
+ kernel/syscalls/ustat.o \
+ kernel/syscalls/open.o \
+ kernel/syscalls/sync.o \
+ kernel/syscalls/iopl.o \
+ kernel/syscalls/msgget.o \
+ kernel/syscalls/pipe.o \
+ kernel/syscalls/shmdt.o \
+ kernel/syscalls/getsid.o \
+ kernel/syscalls/setfsuid.o \
+ kernel/syscalls/signal.o \
+ kernel/syscalls/newfstat.o \
+ kernel/syscalls/mkdir.o \
+ kernel/syscalls/getcwd.o \
+ kernel/syscalls/link.o \
+ kernel/syscalls/msgctl.o \
+ kernel/syscalls/sethostname.o \
+ kernel/syscalls/semctl.o \
+ kernel/syscalls/sysinfo.o \
+ kernel/syscalls/setdomainname.o \
+ kernel/syscalls/getegid.o \
+ kernel/syscalls/personality.o \
+ kernel/syscalls/setregid.o \
+ kernel/syscalls/setgid.o \
+ kernel/syscalls/lstat.o \
+ kernel/syscalls/getuid.o \
+ kernel/syscalls/llseek.o \
+ kernel/syscalls/select.o \
+ kernel/syscalls/ftruncate.o \
+ kernel/syscalls/getpgid.o \
+ kernel/syscalls/brk.o \
+ kernel/syscalls/getrusage.o \
+ kernel/syscalls/sigsuspend.o \
+ kernel/syscalls/writev.o \
+ kernel/syscalls/times.o \
+ kernel/syscalls/ssetmask.o \
+ kernel/syscalls/stat.o \
+ kernel/syscalls/fchdir.o \
+ kernel/syscalls/chdir.o \
+ kernel/syscalls/setgroups.o \
+ kernel/syscalls/newstat.o \
+ kernel/syscalls/creat.o \
+ kernel/syscalls/getdents64.o \
+ kernel/syscalls/getpid.o \
+ kernel/syscalls/read.o \
+ kernel/syscalls/dup.o \
+ kernel/syscalls/utimes.o \
+ kernel/syscalls/semget.o \
+ kernel/syscalls/mount.o \
+ kernel/syscalls/rmdir.o \
+ kernel/syscalls/setrlimit.o \
+ kernel/syscalls/sgetmask.o \
+ kernel/syscalls/pause.o \
+ kernel/syscalls/utime.o \
+ kernel/syscalls/statfs.o \
+ kernel/syscalls/ioperm.o \
+ kernel/syscalls/exit_group.o \
+ kernel/syscalls/ftime.o \
+ kernel/syscalls/truncate.o \
+ kernel/syscalls/pipe2.o \
+ kernel/syscalls/old_mmap.o \
+ kernel/syscalls/olduname.o \
+ kernel/syscalls/kill.o \
+ kernel/syscalls/gettimeofday.o \
+ kernel/syscalls/fchmod.o \
+ kernel/syscalls/fcntl64.o \
+ kernel/syscalls/mprotect.o \
+ kernel/syscalls/getitimer.o \
+ kernel/syscalls/old_select.o \
+ kernel/syscalls/symlink.o \
+ kernel/syscalls/mknod.o \
+ kernel/syscalls/write.o \
+ kernel/syscalls/rename.o \
+ kernel/syscalls/shmat.o \
+ kernel/syscalls/ipc.o \
+ kernel/syscalls/lstat64.o \
+ kernel/syscalls/access.o \
+ kernel/syscalls/getrlimit.o \
+ kernel/syscalls/sigreturn.o \
+ kernel/syscalls/ioctl.o \
+ kernel/syscalls/umask.o \
+ kernel/syscalls/geteuid.o \
+ kernel/syscalls/munmap.o \
+ kernel/syscalls/alarm.o \
+ kernel/syscalls/nanosleep.o \
+ kernel/syscalls/close.o \
+ kernel/syscalls/chroot.o \
+ kernel/syscalls/ftruncate64.o \
+ kernel/syscalls/msgrcv.o \
+ kernel/syscalls/umount2.o \
+ kernel/syscalls/time.o \
+ kernel/syscalls/stime.o \
+ kernel/syscalls/semop.o \
+ kernel/syscalls/newlstat.o \
+ kernel/syscalls/sigpending.o \
+ kernel/syscalls/reboot.o \
+ kernel/syscalls/setuid.o \
+ kernel/syscalls/wait4.o \
+ kernel/syscalls/chown32.o \
+ kernel/syscalls/fcntl.o \
+ kernel/syscalls/fstat64.o \
+ kernel/syscalls/shmctl.o \
+ kernel/syscalls/dup2.o \
+ kernel/syscalls/setpgid.o \
+ kernel/syscalls/getdents.o \
+ kernel/syscalls/getpgrp.o \
+ kernel/syscalls/fchown.o \
+ kernel/syscalls/execve.o \
+ kernel/syscalls/shmget.o \
+ mm/bios_map.o \
+ mm/buddy_low.o \
+ mm/memory.o \
+ mm/page.o \
+ mm/alloc.o \
+ mm/fault.o \
+ mm/mmap.o \
+ mm/swapper.o \
+ fs/filesystems.o \
+ fs/devices.o \
+ fs/buffer.o \
+ fs/fd.o \
+ fs/locks.o \
+ fs/super.o \
+ fs/inode.o \
+ fs/namei.o \
+ fs/elf.o \
+ fs/script.o \
+ fs/minix/super.o \
+ fs/minix/bitmaps.o \
+ fs/minix/inode.o \
+ fs/minix/namei.o \
+ fs/minix/symlink.o \
+ fs/minix/dir.o \
+ fs/minix/file.o \
+ fs/minix/v1_inode.o \
+ fs/minix/v2_inode.o \
+ fs/ext2/inode.o \
+ fs/ext2/super.o \
+ fs/ext2/namei.o \
+ fs/ext2/symlink.o \
+ fs/ext2/dir.o \
+ fs/ext2/file.o \
+ fs/ext2/bitmaps.o \
+ fs/pipefs/super.o \
+ fs/pipefs/fifo.o \
+ fs/pipefs/pipe.o \
+ fs/iso9660/inode.o \
+ fs/iso9660/super.o \
+ fs/iso9660/namei.o \
+ fs/iso9660/dir.o \
+ fs/iso9660/file.o \
+ fs/iso9660/rrip.o \
+ fs/iso9660/symlink.o \
+ fs/procfs/super.o \
+ fs/procfs/inode.o \
+ fs/procfs/namei.o \
+ fs/procfs/dir.o \
+ fs/procfs/file.o \
+ fs/procfs/symlink.o \
+ fs/procfs/tree.o \
+ fs/procfs/data.o \
+ drivers/char/console.o \
+ drivers/char/tty.o \
+ drivers/char/tty_queue.o \
+ drivers/char/vt.o \
+ drivers/char/defkeymap.o \
+ drivers/char/keyboard.o \
+ drivers/char/memdev.o \
+ drivers/char/serial.o \
+ drivers/char/lp.o \
+ drivers/char/fb.o \
+ drivers/char/sysrq.o \
+ drivers/block/dma.o \
+ drivers/block/floppy.o \
+ drivers/block/part.o \
+ drivers/block/ata.o \
+ drivers/block/ata_hd.o \
+ drivers/block/ata_pci.o \
+ drivers/block/atapi.o \
+ drivers/block/atapi_cd.o \
+ drivers/block/ramdisk.o \
+ drivers/pci/pci.o \
+ drivers/video/video.o \
+ drivers/video/vgacon.o \
+ drivers/video/fbcon.o \
+ drivers/video/fonts.o \
+ drivers/video/bga.o \
+ lib/ctype.o \
+ lib/strings.o \
+ lib/printk.o \
+ -o /boot/fiwix
+
+cd ../..
+
+# Checksums
+if match x${UPDATE_CHECKSUMS} xTrue; then
+ sha256sum -o ${pkg}.checksums \
+ /boot/fiwix
+
+ cp ${pkg}.checksums ${srcdir}
+else
+ sha256sum -c ${pkg}.checksums
+fi
diff --git a/sysa/fiwix-1.4.0-lb2/sources b/sysa/fiwix-1.4.0-lb2/sources
@@ -0,0 +1 @@
+https://github.com/rick-masters/Fiwix/releases/download/v1.4.0-lb2/fiwix-1.4.0-lb2.tar.gz 44fb14fb666dcf4f5abf7f49eb3f1d92436b9d7353daa23138ff21e9ec78e30f
diff --git a/sysa/kexec-fiwix/kexec-fiwix.checksums b/sysa/kexec-fiwix/kexec-fiwix.checksums
@@ -1 +1 @@
-afb30f2e80adefc979bdffdb525cf2862897f0beefbb0740fbd05ab3246a32c9 /usr/bin/kexec-fiwix
+4f78914aef30b569a531102998e52a0514d8836204d57ff42bf0a3324968f247 /usr/bin/kexec-fiwix
diff --git a/sysa/kexec-fiwix/src/kexec-fiwix.c b/sysa/kexec-fiwix/src/kexec-fiwix.c
@@ -77,10 +77,10 @@ int main() {
puts("Preparing multiboot info for kernel...");
char cmdline[256];
- sprintf(cmdline, "fiwix console=/dev/ttyS0 root=/dev/ram0 ramdisksize=%d initrd=sysa.ext2", INITRD_MB * 1024);
+ sprintf(cmdline, "fiwix console=/dev/ttyS0 root=/dev/ram0 ramdisksize=%d initrd=sysa.ext2 kexec_proto=linux kexec_size=67000 kexec_cmdline=\"init=/init console=ttyS0\"", INITRD_MB * 1024);
char * boot_loader_name = "kexec-fiwix";
- unsigned int next_avail_mem = 0x8000;
+ unsigned int next_avail_mem = 0x9800;
multiboot_info_t * pmultiboot_info = (multiboot_info_t *) next_avail_mem;
memset(pmultiboot_info, 0, sizeof(multiboot_info_t));
diff --git a/sysa/kexec-linux-1.0.0/files/kexec-linux.c b/sysa/kexec-linux-1.0.0/files/kexec-linux.c
@@ -0,0 +1,82 @@
+/* SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com> */
+/* SPDX-License-Identifier: MIT */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <time.h>
+
+int append_file(FILE *dst_file, char *src_file_name);
+
+
+int main(int argc, char **argv) {
+ char *ramdrive_file_name, *kernel_file_name, *initramfs_file_name;
+ FILE *ramdrive_file;
+ struct stat stats;
+ uint32_t size;
+
+ if (argc < 3) {
+ puts("Usage: fiwix-kexec-linux <ram-drive-name> <kernel-file-name> <initramfs-file-name>");
+ exit(1);
+ }
+
+ ramdrive_file_name = argv[1];
+ kernel_file_name = argv[2];
+ initramfs_file_name = argv[3];
+
+
+ ramdrive_file = fopen(ramdrive_file_name, "wb");
+
+ /* Write length of kernel */
+ if (stat(kernel_file_name, &stats) == 0) {
+ size = (uint32_t) stats.st_size;
+ fwrite(&size, sizeof(size), 1, ramdrive_file);
+ } else {
+ fprintf(stderr, "Cannot stat kernel file '%s'\n", kernel_file_name);
+ exit(1);
+ }
+
+ /* Write length of initramfs */
+ if (stat(initramfs_file_name, &stats) == 0) {
+ size = (uint32_t) stats.st_size;
+ fwrite(&size, sizeof(size), 1, ramdrive_file);
+ } else {
+ fprintf(stderr, "Cannot stat initramfs file '%s'\n", initramfs_file_name);
+ exit(1);
+ }
+
+ if (append_file(ramdrive_file, kernel_file_name)) {
+ fprintf(stderr, "Cannot append kernel '%s'\n", kernel_file_name);
+ exit(1);
+ }
+ if (append_file(ramdrive_file, initramfs_file_name)) {
+ fprintf(stderr, "Cannot append initramfs '%s'\n", initramfs_file_name);
+ exit(1);
+ }
+ fclose(ramdrive_file);
+
+ /* Flush ram drive writes to device */
+ sync();
+
+ /* Perform syscall reboot to initiate kexec */
+ reboot(RB_HALT_SYSTEM);
+}
+
+int append_file(FILE *dst_file, char *src_file_name) {
+ FILE *src_file;
+ char buff[BUFSIZ];
+ size_t n;
+
+ if (src_file = fopen(src_file_name, "rb")) {
+ while ((n = fread(buff, 1, BUFSIZ, src_file)) != 0) {
+ fwrite(buff, 1, n, dst_file );
+ }
+ fclose(src_file);
+ return 0;
+ } else {
+ printf("Cannot open file '%s'\n", src_file_name);
+ return 1;
+ }
+}
diff --git a/sysa/kexec-linux-1.0.0/kexec-linux-1.0.0.sh b/sysa/kexec-linux-1.0.0/kexec-linux-1.0.0.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
+# SPDX-License-Identifier: MIT
+src_get() {
+ :
+}
+
+src_unpack() {
+ dirname=kexec-linux-1.0.0
+ mkdir ${dirname}
+}
+
+src_install() {
+ install -D "kexec-linux" "${DESTDIR}${PREFIX}/bin/kexec-linux"
+}
diff --git a/sysa/kexec-linux-1.0.0/mk/main.mk b/sysa/kexec-linux-1.0.0/mk/main.mk
@@ -0,0 +1,4 @@
+# SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
+# SPDX-License-Identifier: MIT
+kexec-linux: kexec-linux.c
+ gcc -static -m32 -march=i386 -o $@ $^
diff --git a/sysa/lwext4-1.0.0-lb1/files/early-artifacts-needed-after-fiwix.txt b/sysa/lwext4-1.0.0-lb1/files/early-artifacts-needed-after-fiwix.txt
@@ -21,6 +21,7 @@
/usr/bin/checksum-transcriber
/usr/bin/tcc
/usr/bin/tcc-0.9.26
+/usr/bin/kexec-linux
/usr/lib/mes/libc.a
/usr/lib/mes/libgetopt.a
/usr/lib/mes/crt1.o
diff --git a/sysa/lwext4-1.0.0-lb1/files/make_fiwix_initrd.c b/sysa/lwext4-1.0.0-lb1/files/make_fiwix_initrd.c
@@ -71,7 +71,7 @@ static bool open_filedev(void)
file_dev_name_set(input_name);
bd = file_dev_get();
if (!bd) {
- printf("open_filedev: fail\n");
+ puts("open_filedev: fail");
return false;
}
return true;
@@ -85,7 +85,7 @@ bool lwext4_mount(struct ext4_blockdev *bdev, struct ext4_bcache *bcache)
bd = bdev;
if (!bd) {
- printf("lwext4_mount: no block device\n");
+ puts("lwext4_mount: no block device");
return false;
}
@@ -155,21 +155,21 @@ bool copy_file(char *src_path, char *dest_path)
err = ext4_fopen(&dest_file, dest_path, "wb");
if (err != EOK) {
- printf("ext4_open error: %d \n", err);
+ printf("ext4_open error: %d\n", err);
return EXIT_FAILURE;
}
if (src_len > 0) {
err = ext4_fwrite(&dest_file, src_mem, src_len, 0);
if (err != EOK) {
- printf("ext4_fwrite error: %d \n", err);
+ printf("ext4_fwrite error: %d\n", err);
return EXIT_FAILURE;
}
}
err = ext4_fclose(&dest_file);
if (err != EOK) {
- printf("ext4_fclose error: %d \n", err);
+ printf("ext4_fclose error: %d\n", err);
return EXIT_FAILURE;
}
@@ -226,7 +226,7 @@ int main(int argc, char **argv)
err = ext4_mkfs(&fs, bd, &info, F_SET_EXT2_V0);
if (err != EOK) {
- printf("ext4_mkfs error: %d \n", err);
+ printf("ext4_mkfs error: %d\n", err);
return EXIT_FAILURE;
}
@@ -255,32 +255,44 @@ int main(int argc, char **argv)
if (!lwext4_mount(bd, bc))
return EXIT_FAILURE;
- printf("ext4_dir_mk /mp/dev\n");
+ puts("ext4_dir_mk /mp/dev");
err = ext4_dir_mk("/mp/dev");
if (err != EOK) {
- printf("ext4_dir_mk error: %d \n", err);
+ printf("ext4_dir_mk error: %d\n", err);
}
- printf("ext4_mknod /mp/dev/console\n");
+ puts("ext4_mknod /mp/dev/console");
err = ext4_mknod("/mp/dev/console", EXT4_DE_CHRDEV, MKDEV(5, 1));
if (err != EOK) {
- printf("ext4_mknod error: %d \n", err);
+ printf("ext4_mknod error: %d\n", err);
+ return EXIT_FAILURE;
+ }
+ puts("ext4_mknod /mp/dev/ram0");
+ err = ext4_mknod("/mp/dev/ram0", EXT4_DE_BLKDEV, MKDEV(1, 0));
+ if (err != EOK) {
+ printf("ext4_mknod error: %d\n", err);
+ return EXIT_FAILURE;
+ }
+ puts("ext4_mknod /mp/dev/ram1");
+ err = ext4_mknod("/mp/dev/ram1", EXT4_DE_BLKDEV, MKDEV(1, 1));
+ if (err != EOK) {
+ printf("ext4_mknod error: %d\n", err);
return EXIT_FAILURE;
}
copy_file("/usr/bin/kaem", "/mp/init");
copy_file("/sysa/after2.kaem", "/mp/kaem.run");
copy_file_list("/sysa/lwext4-1.0.0-lb1/files/fiwix-file-list.txt");
- printf("ext4_dir_mk /mp/tmp\n");
+ puts("ext4_dir_mk /mp/tmp");
ext4_dir_mk("/mp/tmp");
- printf("ext4_dir_mk /mp/usr\n");
+ puts("ext4_dir_mk /mp/usr");
ext4_dir_mk("/mp/usr");
- printf("ext4_dir_mk /mp/usr/src\n");
+ puts("ext4_dir_mk /mp/usr/src");
ext4_dir_mk("/mp/usr/src");
if (!lwext4_umount())
return EXIT_FAILURE;
- printf("Fiwix ext2 initrd created successfully.\n");
+ puts("Fiwix ext2 initrd created successfully.");
return EXIT_SUCCESS;
}
diff --git a/sysa/lwext4-1.0.0-lb1/lwext4-1.0.0-lb1.checksums b/sysa/lwext4-1.0.0-lb1/lwext4-1.0.0-lb1.checksums
@@ -1 +1 @@
-0a3f0012c01cb5aee0643f1674f265e68b5eeadb37596bcc4fe60aad55c9d3d7 /usr/bin/make_fiwix_initrd
+7b65748dd946f1a5266b2e6d0c9cf7143b4722dae0dd4a02b89d6fba9909e2bd /usr/bin/make_fiwix_initrd
diff --git a/sysa/run.kaem b/sysa/run.kaem
@@ -57,7 +57,7 @@ fi
if match x${BUILD_FIWIX} xTrue; then
# The Fiwix kernel
- pkg="fiwix-1.4.0-lb1"
+ pkg="fiwix-1.4.0-lb2"
cd ${pkg}
kaem --verbose --file ${pkg}.kaem
cd ..
diff --git a/sysa/run2.sh b/sysa/run2.sh
@@ -25,16 +25,20 @@ create_sysb() {
}
go_sysb() {
- # Mount proc for kexec
- mkdir /proc /etc
- mount -t proc proc /proc
- # kexec time
- echo "Loading kernel + sysb initramfs using kexec"
- kexec -l "/boot/linux-4.9.10" --console-serial \
- --initrd="/boot/initramfs-sysb.cpio.gz" \
- --append="init=/init console=ttyS0"
- echo "kexecing into sysb"
- kexec -e
+ if [ "${KERNEL_BOOTSTRAP}" = True ]; then
+ kexec-linux "/dev/ram1" "/boot/linux-4.9.10" "/boot/initramfs-sysb.cpio.gz"
+ else
+ # Mount proc for kexec
+ mkdir /proc /etc
+ mount -t proc proc /proc
+ # kexec time
+ echo "Loading kernel + sysb initramfs using kexec"
+ kexec -l "/boot/linux-4.9.10" --console-serial \
+ --initrd="/boot/initramfs-sysb.cpio.gz" \
+ --append="init=/init console=ttyS0"
+ echo "kexecing into sysb"
+ kexec -e
+ fi
}
build automake-1.15.1
@@ -87,6 +91,8 @@ grep --no-filename '^build' "${SOURCES}"/run*.sh | grep -v musl-1.2.3 | sed "s/b
done
if [ "${CHROOT}" = False ] || [ "${BUILD_KERNELS}" = True ]; then
+ build kexec-linux-1.0.0
+
build kexec-tools-2.0.22
build linux-4.9.10
@@ -96,12 +102,7 @@ build musl-1.2.3 '' no-patches
if [ "${CHROOT}" = False ]; then
create_sysb
- if [ "${KERNEL_BOOTSTRAP}" = True ]; then
- echo "Kernel bootstrapping successful."
- echo "NOTE: Transition to Linux and building remaining packages is under development."
- else
- go_sysb
- fi
+ go_sysb
else
# In chroot mode transition directly into System C.
SYSC=/sysc_image
diff --git a/sysb/run.sh b/sysb/run.sh
@@ -65,15 +65,15 @@ if [ -z "${DISK}" ] || ! [ -e "/dev/${DISK}" ]; then
echo "DISK=${DISK}" >> /usr/src/bootstrap.cfg
fi
-# Is it a full disk, and not a partition
+# Is it a full disk, and not a partition?
# shellcheck disable=SC2012
if [ $(($(ls -l "/dev/${DISK}" | sed "s/.*, *//" | sed "s/ .*//") % 8)) -eq 0 ]; then
- if ! fdisk -l "/dev/${DISK}" | grep -qE "${DISK}p?[0-9]" ; then
- echo "Creating partition table and partition"
- echo ";" | sfdisk "/dev/${DISK}"
- mkfs.ext4 "/dev/${DISK}1"
- DISK="${DISK}1"
- fi
+ echo "Creating partition table..."
+ echo ";" | sfdisk "/dev/${DISK}"
+ fdisk -l "/dev/${DISK}"
+ echo "Creating ext4 partition..."
+ mkfs.ext4 "/dev/${DISK}1"
+ DISK="${DISK}1"
fi
echo "export DISK=${DISK}" >> /usr/src/bootstrap.cfg