Compare commits

..

34 Commits

Author SHA1 Message Date
Jørn Guldberg 3dbebef054 Kernel updates to support LSFS 5 years ago
Jørn Guldberg 2c5a5ebbda Mid updating file system, SingOS does not support updated version yet 6 years ago
Jørn Guldberg 82db39baba Update on file system, FScurrently not working correct 6 years ago
Jørn Guldberg c41a7d7378 updates 6 years ago
Jørn Guldberg b19f629330 version 0.0.6.0: improved xex command, data segment also set correct, which should mean fully correct termination of an executable file 6 years ago
Jørn Guldberg 30d6cf9f44 fix #6, isseu found elsewhere. Improved 'xex' command, and print return value from the program 6 years ago
Jørn Guldberg 27c47ff744 first xex-file has now been executed and returned to safe kernel state 6 years ago
Jørn Guldberg 6e3bf898b6 xex needs more work 6 years ago
Jørn Guldberg c47b2fb780 Command 'xex' added, going to be the command for executing a program from a file 6 years ago
Jørn Guldberg 656525f1e3 Start working on 32-bit disk driver 6 years ago
Jørn Guldberg 7f1d3f1ea2 no 6 years ago
Jørn Guldberg 8bc73f0a7e Svim Upgrade 6 years ago
Jakob Galle Kjær-Kammersgaard bad2c10a8b Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard 34ae935c88 Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard e97a86c604 Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard e9cafcd9fe Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard aac061f8b3 Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard 1ac75a9f24 Fixed typo 7 years ago
Jakob Galle Kjær-Kammersgaard adb5d0a0ed Update 'SingOS_Coding_Practice.md' 7 years ago
Jakob Galle Kjær-Kammersgaard 62173b27c4 A first draft at formalizing a common coding practice for SingOS development 7 years ago
Jørn Guldberg a1f139b037 svim - redraw bug fixed 7 years ago
Jørn Guldberg 5cf71bbaa5 svim version 0.1.0 - Saves correct when cusor is mid text, when use tab, it converts to two sapces 7 years ago
Jørn Guldberg aac2b53e5e Navigation and editing in place in svim works 7 years ago
Jørn Guldberg f6b8c72451 Arrow up works in svim, now wokring on arrow down 7 years ago
Jørn Guldberg 525c2be522 Trying to fix svim when up key ispressed 7 years ago
Jørn Guldberg c6cf326c53 svim can now go back in text and edit it 7 years ago
Jørn Guldberg d2706a4530 Version 0.0.5 7 years ago
Jørn Flemming Guldberg 2835033a32 Merge branch 'jorn_dev' of SingOS/SingOS into master 7 years ago
Jørn Guldberg fab5855a0f Svim update - can now delete linebreak 7 years ago
Jakob Kjær-Kammersgaard e5bd4993d8 Merged in refactor32 branch 7 years ago
Jakob Kjær-Kammersgaard 823955c556 Merge remote-tracking branch 'origin/refactor32' 7 years ago
Jakob Galle Kjær-Kammersgaard 90de25d403 Don't look at diff! 7 years ago
Jørn Flemming Guldberg 0023d5dfae Update 'README.md' 7 years ago
Jakob Galle Kjær-Kammersgaard 80ac379fc1 Captions for screenshots 7 years ago
  1. 8
      CLI/CLI.nasm
  2. 11
      README.md
  3. 101
      SingOS_Coding_Practice.md
  4. 8
      bootloader.nasm
  5. 278
      driver/disk_driver.nasm
  6. 2
      filesystems/lsfs/lsfs.nasm
  7. 6
      filesystems/lsfs/test_lsfs.nasm
  8. 104
      kernel.nasm
  9. 22
      lib/os_lib.nasm
  10. 499
      lib/svim.nasm
  11. 171
      lib/xex.nasm
  12. 389
      vbr.nasm

8
CLI/CLI.nasm

@ -158,9 +158,9 @@ CLI_EXECUTE:
ret
.tmp dw 0
.Num_Commands dw 10
.Command_Name_List dw .CMD1, .CMD2, .CMD3, .CMD4, .CMD5, .CMD6, .CMD7, .CMD8, .CMD9, .CMDa
.Command_Function_Pointers dw dumpmem_hardcoded_args, keyprint, svim, lsfs_list_files_command, lsfs_create_file, lsfs_format_disk, lsfs_get_fs_info, os_clear_screen, print_help_message, Go32Bit
.Num_Commands dw 12
.Command_Name_List dw .CMD1, .CMD2, .CMD3, .CMD4, .CMD5, .CMD6, .CMD7, .CMD8, .CMD9, .CMDa, .CMDb, .CMDc
.Command_Function_Pointers dw dumpmem_hardcoded_args, keyprint, svim, lsfs_list_files_command, lsfs_create_file, lsfs_format_disk, lsfs_get_fs_info, os_clear_screen, print_help_message, Go32Bit, xex, lsfs_create_file
.CMD1 db 'dumpmem', 0
.CMD2 db 'keyprint', 0
.CMD3 db 'svim', 0
@ -171,5 +171,7 @@ CLI_EXECUTE:
.CMD8 db 'clear', 0
.CMD9 db 'help', 0
.CMDa db 'go32', 0
.CMDb db 'xex', 0
.CMDc db 'cf', 0 ; short for createfile

11
README.md

@ -12,8 +12,13 @@ It will also be posible to switch between 16, 32 and 64-bit mode
such that anything on very low level can be tested.
## Screenshots
![Screenshot - svim edit](screenshots/SingSvimEdit.png)
![Screenshot - colored circle](screenshots/Sing32ColoredCircles.png)
> Svim, everyone's favorite text editor for SingOS
> ![Screenshot - svim edit](screenshots/SingSvimEdit.png)
 
> The spectacle that is the 32 bit protected mode SingOS placeholder
> ![Screenshot - colored circle](screenshots/Sing32ColoredCircles.png)
## Build Instructions
You can build and run the OS with following command
@ -43,7 +48,7 @@ If you only want to compile the binary:
If you want to run SingOS on real hardware we recommend running it from a usb thumb drive:
**WARNING:** *For now you should only run SingOS on a PC with no important data, preferably some old junker.*
**WARNING:** *For now you should only run SingOS on a PC with no important data.*
```sh
sudo dd if=/<PATH TO SING OS>/SingOS.img of=/dev/<DEVICE NUMBER FOR USB DRIVE> status=progress oflag=sync
```

101
SingOS_Coding_Practice.md

@ -0,0 +1,101 @@
# SingOs Coding Practice
*Version 1 -- A first draft at formalizing a common coding practice for SingOS Development*
## On naming
We encourage long but descriptive identifier names like,
token_string_to_id_map
as opposed to,
tok_map (BAD)
`(Yes, it's a made up example)`.
Short names like 'i' and 'j' may be
used for super obvious iteration indexes only,
otherwise, if the body of the loop is big,
we still prefer something more explicit like:
token_index
## On casing
We use snake-case for all identifiers consisting of multiple words;
this means that words are underscore seperated.
For variable and procedure names, every letter is lowercase:
our_very_important_variable
our_very_important_procedure
For all typenames (`structs`, `enums`, `unions`, etc.),
every word begins with a capitalized letter:
Our_Very_Important_Type
(An exception is made for primitive types like `int`, `float`, `double`, etc).
For value constants (`#defines`), every letter is uppercase (all-caps):
OUR_VERY_IMPORTANT_CONSTANT
Macros acting like procedures should be capitalized like procedures,
but with parameter names in all-caps:
our_very_important_macro(PARAMETER, OTHER_PARAMETER)
## On indentation
We use 4 spaces per indent, at least in C-style languages. (^:
## On brace-placement
What do we prefer?
This:
if (something)
{
do_stuff();
}
else
{
this_other_thing();
}
Or this:
if (something) {
do_stuff();
}
else {
this_other_thing();
}
## On return statements
We prefer an explicit else case even though a return was found in an above branch:
if (some_condition)
{
return "Olga";
}
else
{
return "Finn";
}
As opposed to:
(BAD)
if (some_condition)
{
return "Olga";
}
return "Finn";
(BAD)

8
bootloader.nasm

@ -2,7 +2,7 @@ ORG 0x7C00
BITS 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Bootloader for SingOS
; version 0.1.0.9-exp
; version 0.1.0.10-exp
;
; Please edit the version number if any changes is made, the last number
; represent the build number.
@ -150,7 +150,7 @@ print:
ret
data:
message db 'Bootloader for SingOS! v0.1.0.9-exp',13,10,0
message db 'Bootloader for SingOS! v0.1.0.10-exp',13,10,0
enter_debug_mode db 'Press d to enter bootloader debug mode',13,10,0
enter_system_check db 'Performing system check:',13,10,0
sys_check_ok db 'System check ok', 13, 10, 0
@ -163,9 +163,9 @@ data:
times 446-($-$$) db 0 ; First partion entry
db 0x80 ; active partition
db 0, 0x00, 0x17 ; First sector CHS
db 0x00 ; Disk type (Other)
db 0x18 ; Disk type (Other) (Why 18, answer ':' ^ ')' )
db 0xff, 0xff, 0xff ; Ending CHS values
db 0x17, 0, 0, 0x00 ; Staring LBA
db 0x18, 0, 0, 0x00 ; Staring LBA
db 0, 0xff, 0xff, 0xff ; Size
db 0x00

278
driver/disk_driver.nasm

@ -0,0 +1,278 @@
; Borraowed from https://wiki.osdev.org/ATA_PIO_Mode
; do a singletasking PIO ATA read
; inputs: ebx = # of sectors to read, edi -> dest buffer, esi -> driverdata struct, ebp = 4b LBA
; Note: ebp is a "relative" LBA -- the offset from the beginning of the partition
; outputs: ebp, edi incremented past read; ebx = 0
; flags: zero flag set on success, carry set on failure (redundant)
read_ata_st:
push edx
push ecx
push eax
test ebx, ebx ; # of sectors < 0 is a "reset" request from software
js short .reset
cmp ebx, 0x3fffff ; read will be bigger than 2GB? (error)
stc
jg short .r_don
mov edx, [esi + dd_prtlen] ; get the total partition length (sectors)
dec edx ; (to avoid handling "equality" case)
cmp edx, ebp ; verify ebp is legal (within partition limit)
jb short .r_don ; (carry is set automatically on an error)
cmp edx, ebx ; verify ebx is legal (forget about the ebx = edx case)
jb short .r_don
sub edx, ebx ; verify ebp + ebx - 1 is legal
inc edx
cmp edx, ebp ; (the test actually checks ebp <= edx - ebx + 1)
jb short .r_don
mov dx, [esi + dd_dcr] ; dx = alt status/DCR
in al, dx ; get the current status
test al, 0x88 ; check the BSY and DRQ bits -- both must be clear
je short .stat_ok
.reset:
call srst_ata_st
test ebx, ebx ; bypass any read on a "reset" request
jns short .stat_ok
xor ebx, ebx ; force zero flag on, carry clear
jmp short .r_don
.stat_ok:
; preferentially use the 28bit routine, because it's a little faster
; if ebp > 28bit or esi.stLBA > 28bit or stLBA+ebp > 28bit or stLBA+ebp+ebx > 28bit, use 48 bit
cmp ebp, 0xfffffff
jg short .setreg
mov eax, [esi + dd_stLBA]
cmp eax, 0xfffffff
jg short .setreg
add eax, ebp
cmp eax, 0xfffffff
jg short .setreg
add eax, ebx
cmp eax, 0xfffffff
.setreg:
mov dx, [esi + dd_tf] ; dx = IO port base ("task file")
jle short .read28 ; test the flags from the eax cmp's above
.read48:
test ebx, ebx ; no more sectors to read?
je short .r_don
call pio48_read ; read up to 256 more sectors, updating registers
je short .read48 ; if successful, is there more to read?
jmp short .r_don
.read28:
test ebx, ebx ; no more sectors to read?
je short .r_don
call pio28_read ; read up to 256 more sectors, updating registers
je short .read28 ; if successful, is there more to read?
.r_don:
pop eax
pop ecx
pop edx
ret
;ATA PI0 28bit singletasking disk read function (up to 256 sectors)
; inputs: ESI -> driverdata info, EDI -> destination buffer
; BL = sectors to read, DX = base bus I/O port (0x1F0, 0x170, ...), EBP = 28bit "relative" LBA
; BSY and DRQ ATA status bits must already be known to be clear on both slave and master
; outputs: data stored in EDI; EDI and EBP advanced, EBX decremented
; flags: on success Zero flag set, Carry clear
pio28_read:
add ebp, [esi + dd_stLBA] ; convert relative LBA to absolute LBA
mov ecx, ebp ; save a working copy
mov al, bl ; set al= sector count (0 means 256 sectors)
or dl, 2 ; dx = sectorcount port -- usually port 1f2
out dx, al
mov al, cl ; ecx currently holds LBA
inc edx ; port 1f3 -- LBAlow
out dx, al
mov al, ch
inc edx ; port 1f4 -- LBAmid
out dx, al
bswap ecx
mov al, ch ; bits 16 to 23 of LBA
inc edx ; port 1f5 -- LBAhigh
out dx, al
mov al, cl ; bits 24 to 28 of LBA
or al, byte [esi + dd_sbits] ; master/slave flag | 0xe0
inc edx ; port 1f6 -- drive select
out dx, al
inc edx ; port 1f7 -- command/status
mov al, 0x20 ; send "read" command to drive
out dx, al
; ignore the error bit for the first 4 status reads -- ie. implement 400ns delay on ERR only
; wait for BSY clear and DRQ set
mov ecx, 4
.lp1:
in al, dx ; grab a status byte
test al, 0x80 ; BSY flag set?
jne short .retry
test al, 8 ; DRQ set?
jne short .data_rdy
.retry:
dec ecx
jg short .lp1
; need to wait some more -- loop until BSY clears or ERR sets (error exit if ERR sets)
.pior_l:
in al, dx ; grab a status byte
test al, 0x80 ; BSY flag set?
jne short .pior_l ; (all other flags are meaningless if BSY is set)
test al, 0x21 ; ERR or DF set?
jne short .fail
.data_rdy:
; if BSY and ERR are clear then DRQ must be set -- go and read the data
sub dl, 7 ; read from data port (ie. 0x1f0)
mov cx, 256
rep insw ; gulp one 512b sector into edi
or dl, 7 ; "point" dx back at the status register
in al, dx ; delay 400ns to allow drive to set new values of BSY and DRQ
in al, dx
in al, dx
in al, dx
; After each DRQ data block it is mandatory to either:
; receive and ack the IRQ -- or poll the status port all over again
inc ebp ; increment the current absolute LBA
dec ebx ; decrement the "sectors to read" count
test bl, bl ; check if the low byte just turned 0 (more sectors to read?)
jne short .pior_l
sub dx, 7 ; "point" dx back at the base IO port, so it's unchanged
sub ebp, [esi + dd_stLBA] ; convert absolute lba back to relative
; "test" sets the zero flag for a "success" return -- also clears the carry flag
test al, 0x21 ; test the last status ERR bits
je short .done
.fail:
stc
.done:
ret
;ATA PI0 33bit singletasking disk read function (up to 64K sectors, using 48bit mode)
; inputs: bx = sectors to read (0 means 64K sectors), edi -> destination buffer
; esi -> driverdata info, dx = base bus I/O port (0x1F0, 0x170, ...), ebp = 32bit "relative" LBA
; BSY and DRQ ATA status bits must already be known to be clear on both slave and master
; outputs: data stored in edi; edi and ebp advanced, ebx decremented
; flags: on success Zero flag set, Carry clear
pio48_read:
xor eax, eax
add ebp, [esi + dd_stLBA] ; convert relative LBA to absolute LBA
; special case: did the addition overflow 32 bits (carry set)?
adc ah, 0 ; if so, ah = LBA byte #5 = 1
mov ecx, ebp ; save a working copy of 32 bit absolute LBA
; for speed purposes, never OUT to the same port twice in a row -- avoiding it is messy but best
;outb (0x1F2, sectorcount high)
;outb (0x1F3, LBA4)
;outb (0x1F4, LBA5) -- value = 0 or 1 only
;outb (0x1F5, LBA6) -- value = 0 always
;outb (0x1F2, sectorcount low)
;outb (0x1F3, LBA1)
;outb (0x1F4, LBA2)
;outb (0x1F5, LBA3)
bswap ecx ; make LBA4 and LBA3 easy to access (cl, ch)
or dl, 2 ; dx = sectorcount port -- usually port 1f2
mov al, bh ; sectorcount -- high byte
out dx, al
mov al, cl
inc edx
out dx, al ; LBA4 = LBAlow, high byte (1f3)
inc edx
mov al, ah ; LBA5 was calculated above
out dx, al ; LBA5 = LBAmid, high byte (1f4)
inc edx
mov al, 0 ; LBA6 is always 0 in 32 bit mode
out dx, al ; LBA6 = LBAhigh, high byte (1f5)
sub dl, 3
mov al, bl ; sectorcount -- low byte (1f2)
out dx, al
mov ax, bp ; get LBA1 and LBA2 into ax
inc edx
out dx, al ; LBA1 = LBAlow, low byte (1f3)
mov al, ah ; LBA2
inc edx
out dx, al ; LBA2 = LBAmid, low byte (1f4)
mov al, ch ; LBA3
inc edx
out dx, al ; LBA3 = LBAhigh, low byte (1f5)
mov al, byte [esi + dd_sbits] ; master/slave flag | 0xe0
inc edx
and al, 0x50 ; get rid of extraneous LBA28 bits in drive selector
out dx, al ; drive select (1f6)
inc edx
mov al, 0x24 ; send "read ext" command to drive
out dx, al ; command (1f7)
; ignore the error bit for the first 4 status reads -- ie. implement 400ns delay on ERR only
; wait for BSY clear and DRQ set
mov ecx, 4
.lp1:
in al, dx ; grab a status byte
test al, 0x80 ; BSY flag set?
jne short .retry
test al, 8 ; DRQ set?
jne short .data_rdy
.retry:
dec ecx
jg short .lp1
; need to wait some more -- loop until BSY clears or ERR sets (error exit if ERR sets)
.pior_l:
in al, dx ; grab a status byte
test al, 0x80 ; BSY flag set?
jne short .pior_l ; (all other flags are meaningless if BSY is set)
test al, 0x21 ; ERR or DF set?
jne short .fail
.data_rdy:
; if BSY and ERR are clear then DRQ must be set -- go and read the data
sub dl, 7 ; read from data port (ie. 0x1f0)
mov cx, 256
rep insw ; gulp one 512b sector into edi
or dl, 7 ; "point" dx back at the status register
in al, dx ; delay 400ns to allow drive to set new values of BSY and DRQ
in al, dx
in al, dx
in al, dx
; After each DRQ data block it is mandatory to either:
; receive and ack the IRQ -- or poll the status port all over again
inc ebp ; increment the current absolute LBA (overflowing is OK!)
dec ebx ; decrement the "sectors to read" count
test bx, bx ; check if "sectorcount" just decremented to 0
jne short .pior_l
sub dx, 7 ; "point" dx back at the base IO port, so it's unchanged
sub ebp, [esi + dd_stLBA] ; convert absolute lba back to relative
; this sub handles the >32bit overflow cases correcty, too
; "test" sets the zero flag for a "success" return -- also clears the carry flag
test al, 0x21 ; test the last status ERR bits
je short .done
.fail:
stc
.done:
ret
; do a singletasking PIO ata "software reset" with DCR in dx
srst_ata_st:
push eax
mov al, 4
out dx, al ; do a "software reset" on the bus
xor eax, eax
out dx, al ; reset the bus to normal operation
in al, dx ; it might take 4 tries for status bits to reset
in al, dx ; ie. do a 400ns delay
in al, dx
in al, dx
.rdylp:
in al, dx
and al, 0xc0 ; check BSY and RDY
cmp al, 0x40 ; want BSY clear and RDY set
jne short .rdylp
pop eax
ret

2
filesystems/lsfs/lsfs.nasm

@ -1,6 +1,6 @@
BITS 16
%define LSFS_FIX_FILE_SIZE 0x10
%define LSFS_magic_start_sector 24 ; This is the sector right after the SingOS kernel stops and is a magic number that has to be changed when the kernel grows.
%define LSFS_magic_start_sector 23 ; This is the sector right after the SingOS kernel stops and is a magic number that has to be changed when the kernel grows.
%define FSCI_sector 88
lsfs_check_extended_support:

6
filesystems/lsfs/test_lsfs.nasm

@ -1,7 +1,7 @@
BITS 16
%define LSFS_magic_start_sector 24
%define LSFS_magic_start_sector 23
;This is for the FSCI, where this is stored on the disk.
lsfs_format_disk_buffer db 'LSFS v0.1.1-exp', 13, 10, '(LessSimpelFileSystem)', 13, 10, 'Developed to SingOS', 13, 10, 'by Jorn Guldberg', 13, 10, 0 ; 66 chars + 8 bytes
lsfs_format_disk_buffer db 'LSFS v0.1.3-exp', 13, 10, '(LessSimpelFileSystem)', 13, 10, 'Developed to SingOS', 13, 10, 'by Jorn Guldberg', 13, 10, 0 ; 66 chars + 8 bytes
times 506-($-$$) db 0
dw LSFS_magic_start_sector, 3, 2306 ; Start index, number of files, next free index
; 4 is right now the next number of file
@ -13,7 +13,7 @@ lfsf_systemcall:
int 0x16
mov ah, 0x0e
mov al, 65 ; backspace
mov al, 66 ; backspace
int 0x10 ; print char
ret

104
kernel.nasm

@ -1,30 +1,91 @@
BITS 16
ORG 0x512
start_sing:
; loading essentials for SingOS to run
mov ax, 0x0150
mov ds, ax
mov es, ax
; Setup stack
mov ax, 0x8fc0
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack
mov bp, sp
mov [global_disk_FSCI_LBA_position], bx ; passed by the volume boot record.
mov [global_disk_identifier], dl ; saving disk_identifier, this is the number the disk that we are booting from.
; This number is set by the bios
;call lsfs_check_extended_support ; Check that the int 0x13 extended read and write is available
jmp sing_loaded
; setup file system information
; mov cx, [global_disk_FSCI_LBA_position]
; mov WORD [Parameter_Struct.buffer_segment], 0x50
; mov WORD [Parameter_Struct.buffer_address], 0x2000 ; Heap memory start adresses for the file system
; mov WORD [Parameter_Struct.buffer_size], 0x3000 ; End address for the heap
; mov WORD [Parameter_Struct.data_length], cx
;
; mov bx, ds
; mov cx, Parameter_Struct
; mov ax, 0x1
; push cx
; push bx
; push ax
; mov cx, 0x50
; mov ds, cx
; mov es, cx
; call 0x50:0x00
; add sp, 0x6 ; skip the paramerts
; mov cx, 0x0150
; mov ds, cx
; mov es, cx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SYSTEM CALL TABLE STARTING AT POSITION 0x0050:0x0000
; To already support 64-bit, the entries is 64-bit
; But in 16-bit, the adresses is only 16-bit
; These are stored in the first 16-bits
; There is reserved 2 sectors to the table witch means that we have room for
; 128 System Calls
; |----|----------------------------------------------------------------------------|
; | 1 | Master Table| call [0x0050:0x0000] Pointer to the Master File Table |
; |----|----------------------------------------------------------------------------|
; | 2 | FILE SYSTEM | call [0x0050:0x0008] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 3 | OS_LIB | call [0x0050:0x0016] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 1 | FILE SYSTEM | call [0x0050:0x0000] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 2 | OS_LIB | call [0x0050:0x0008] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor bx, bx
mov al, 0x49
mov ah, 0x0E
int 0x10
jmp 0x0150:sing_loaded
;%include "mem_lib/mem_lib.nasm"
%include "lib/os_lib.nasm"
%include "lib/string.nasm"
%include "lib/debug_tools.nasm"
%include "lib/std_power.nasm"
%include "lib/svim.nasm"
%include "lib/xex.nasm"
%include "filesystems/lsfs/lsfs.nasm" ; old filesystem was ;%include "vsfs/vsfs.nasm"
%include "CLI/CLI.nasm"
sing_loaded: ; SingOS is ready for the user:
mov ax, 0x8fc0
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack
mov bp, sp
xor bx, bx
mov al, 0x49
mov ah, 0x0E
int 0x10
; mov ax, 0x8fc0
; mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
; mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack
; mov bp, sp
;
sing_ready: ; SingOS is ready for the user:
%if 1
%if 0
call Go32Bit
%endif
@ -272,7 +333,6 @@ wait_for_key:
jmp .no_str
;
global_vars:
global_lsfs_master_record dw 2064 ; this is the index of the start of the master table for the filesystem
; This should maby contain more information.
@ -285,23 +345,27 @@ global_vars:
; creation of a new file.
global_disk_identifier db 0 ; set by the bios passed by the bootloader,
; this is the bios ID
global_disk_FSCI_LBA_position db 0
data:
welcome db "###############################################################################", 13, 10, "# Welcome to SingOS VERSION 0.0.4.5-exp #", 13, 10, "# #", 13, 10, "###############################################################################", 13, 10, 'Press ESC to halt.', 13, 10, 13, 10, 0
welcome db "###############################################################################", 13, 10, "# Welcome to SingOS - VERSION 0.0.6.1 #", 13, 10, "# #", 13, 10, "###############################################################################", 13, 10, 'Press ESC to halt.', 13, 10, 13, 10, 0
exit_message db 13, 10, 'Goodbye from SingOS',13,10,'The system has halted.', 0
command_line db 13, 10, 'groot@SingOS $ ', 0
number_one_zstring db '71', 0
example_format_string db "(%x-%x-%x){%d%%}",0
;times 131072-($-$$) db 0 ; 256 sectos
;GLOBAL_VSFS_START db 'VSFS v0.1' ; sector 257 reserved for file system information
%include "go32bit.nasm"
; times ((1<<13)-($-$$)) db 0 ; sector 258 to sector 2048 should be avaliable to the filesystem.
Parameter_Struct:
.path dw 0x00 ; char*
.new_path dw 0x00 ; char*
.buffer_segment dw 0x00 ; int
.buffer_address dw 0x00 ; int
.buffer_size dw 0x00 ; int
.data_length dw 0x00 ; int
.byte_offset_into_file dw 0x00 ; int
.entry_kind dw 0x00 ; Table_Entry_Kind
times ((1<<20)-($-$$) - 26) db 0 ; sector 258 to sector 2048 should be avaliable to the filesystem.
magic_string_end_of_SingOS_kernel db '** END OF KERNEL SingOS **'
;times 131072-($-$$) db 0 ; 256 sectos
;GLOBAL_VSFS_START db 'VSFS v0.1' ; sector 257 reserved for file system information
times ((1<<24)-($-$$)) db 0
%include "go32bit.nasm"

22
lib/os_lib.nasm

@ -45,6 +45,28 @@ printALChar:
int 0x10
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print_reverse:
; Prints string in si
; IN bx: adress of string
; IN cx: length
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
add bx, cx
.printchar:
mov BYTE al, [bx] ; Load byte at address SI into AL, and increment SI
test al, al
jz .done ; If the character is zero (NUL), stop writing the string
cmp cx, 0
jz .done
int 0x10 ; Otherwise, print the character via 'int 0x10'
dec bx
dec cx
jmp .printchar ; Repeat for the next character
.done:
ret
; Changing the screen the user i looking at.
; value in 'al' is the screen we want to switch to.
; starting from 0x00

499
lib/svim.nasm

@ -1,9 +1,19 @@
BITS 16
%define svim_starting_row_number_for_text 2
%define svim_end_row_number_for_text 24
%define svim_magic_buffer_size 2048
svim:
pusha ; save state before program
sub sp, svim_magic_buffer_size
mov [.buffer_for_svim_base], sp
mov [buffer_for_svim_base_left_of_cursor], sp
sub sp, svim_magic_buffer_size
mov [buffer_for_svim_base_right_of_cursor], sp
mov bx, sp
mov BYTE [bx], 0 ; be sure that the first byte is zero.
mov WORD [svim_counter_char_in_left_buffer], 0 ; reset these to zero
mov WORD [svim_counter_char_in_right_buffer], 0
mov WORD [svim_get_cursor_distance_to_next_line_break], 0
mov BYTE [svim_save_on_exit], 0
call os_clear_screen
@ -13,10 +23,10 @@ svim:
mov dh, 0x00 ; row zero
mov dl, 0x17 ; coloumn zero
int 0x10
mov si, .welcome_svim_select_file
mov si, welcome_svim_select_file
call print
call printCRLF
mov si, .seperate_line
mov si, seperate_line
call print
call lsfs_list_files_command
@ -29,10 +39,10 @@ svim:
mov dl, 0x00 ; coloumn zero
int 0x10
mov si, .welcome_svim
mov si, welcome_svim
call print
call printCRLF
mov si, .welcome_svim_enter_fileindex
mov si, welcome_svim_enter_fileindex
call print
; Ask the user for the filename
@ -52,7 +62,7 @@ svim:
je .loop_no_push
pop cx
sub cx, 1
mov bx, [.buffer_for_svim_base]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, cx
mov BYTE [bx], 0
; Go back one space
@ -74,7 +84,7 @@ svim:
mov ah, 0x0E
int 0x10 ; print char
pop cx
mov bx, [.buffer_for_svim_base]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, cx
mov [bx], al
add cx, 1
@ -87,67 +97,64 @@ svim:
.fileindex_done:
pop cx ; Cleanup, and now contain filename size
mov ax, cx
add ax, [.buffer_for_svim_base]
add ax, [buffer_for_svim_base_left_of_cursor]
mov bx, ax
mov BYTE [bx], 0
mov si, [.buffer_for_svim_base]
mov si, [buffer_for_svim_base_left_of_cursor]
call zstring_to_integer ; ax now contain the interger index for the file
mov [.fileindex_for_open_file], ax ; save the file index
mov [fileindex_for_open_file], ax ; save the file index
call os_clear_screen
; move cursor to the bootom
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bh, 0x00 ; page number 0
mov dh, 0x17 ; row zero
mov dl, 0x00 ; coloumn zero
int 0x10
call svim_redraw_window
; LOAD FILE
; Prepare to ask the filesystem to load the file
; The file system should be given the file_id and the buffer where we can write
mov ax, [fileindex_for_open_file]
mov bx, [buffer_for_svim_base_left_of_cursor]
call lsfs_read_file
mov si, .seperate_line
call print
mov si, .welcome_svim
call print
;mov bx, [buffer_for_svim_base_left_of_cursor]
;add bx, svim_magic_buffer_size - 2
;mov ax, [bx]
mov [svim_counter_char_in_left_buffer], ax
; move cursor to the top
;mov [svim_counter_char_in_left_buffer], ax
; print buffer
;mov si, [buffer_for_svim_base_left_of_cursor]
;mov es, si
;call print
.svim_loop:
; Redraw the whole text,
; move cursor to the top, where the text has to start (line 2)
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bh, 0x00 ; page number 0
mov dh, 0x00 ; row zero
mov dl, 0x00 ; coloumn zero
mov dh, 0x02 ; row
mov dl, 0x00 ; coloumn
int 0x10
; Load from disk and, enter it, into the buffer
mov si, .welcome_svim_select_file
call print
mov ax, [.fileindex_for_open_file]
call dumpax10
call printCRLF
mov si, .seperate_line
mov si, [buffer_for_svim_base_left_of_cursor]
call print
; LOAD FILE
; Prepare to ask the filesystem to load the file
; The file system should be given the file_id and the buffer where we can write
mov ax, [.fileindex_for_open_file]
mov bx, [.buffer_for_svim_base]
call lsfs_read_file
; Check if there is somthing to the right of the cursor that should be written to screen
mov cx, [svim_counter_char_in_right_buffer]
cmp cx, 0 ; Nothing to be written
je .no_write_right_of_the_cursor
call get_cursor_position
push dx
mov bx, [buffer_for_svim_base_right_of_cursor]
dec bx
mov cx, [svim_counter_char_in_right_buffer]
call print_reverse
pop dx
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bx, 0x00 ; page zero
int 0x10
;mov bx, [.buffer_for_svim_base]
;add bx, svim_magic_buffer_size - 2
;mov ax, [bx]
mov [.buffer_counter_svim], ax
; print buffer
mov si, [.buffer_for_svim_base]
mov es, si
call print
.svim_loop:
.no_write_right_of_the_cursor:
xor bx, bx
xor cx, cx
xor dx, dx
@ -155,98 +162,384 @@ svim:
int 0x16
cmp ax, 0x1c0d ; enter key
jne .no_enter
mov bx, [.buffer_for_svim_base]
add bx, [.buffer_counter_svim]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, [svim_counter_char_in_left_buffer]
mov BYTE [bx], 13 ; put char in the buffer
mov BYTE [bx + 1], 10 ; put char in the buffer
mov bx, [.buffer_counter_svim]
mov bx, [svim_counter_char_in_left_buffer]
add bx, 0x02
mov [.buffer_counter_svim], bx
mov [svim_counter_char_in_left_buffer], bx
xor bx, bx
xor cx, cx
xor dx, dx
mov ax, 0x0e0d
int 0x10
mov ax, 0x0e0a
int 0x10
call svim_redraw_window
jmp .svim_loop
.no_enter:
cmp ax, 0x4be0 ; left key
jne .check_up_key
call handle_left_key_pressed
jmp .svim_loop
.check_up_key:
cmp ax, 0x48e0 ; up key
jne .check_right_key
call handle_up_key_pressed
jmp .svim_loop
.check_right_key:
cmp ax, 0x4de0 ; right key
jne .check_down_key
call handle_right_key_pressed
jmp .svim_loop
.check_down_key:
cmp ax, 0x50e0 ; down key
jne .check_tab_key
call handle_down_key_pressed
jmp .svim_loop
.check_tab_key:
cmp ax, 0x0f09 ; tab key
jne .no_special_key_pressed
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, [svim_counter_char_in_left_buffer]
mov BYTE [bx], 0x20 ; put space char in the buffer
mov BYTE [bx + 1], 0x20 ; put space char in the buffer
mov bx, [svim_counter_char_in_left_buffer]
add bx, 0x02
mov [svim_counter_char_in_left_buffer], bx
call svim_redraw_window
jmp .svim_loop
jmp .svim_loop
.no_special_key_pressed:
cmp ax, 0x11b ; ESC key
je .end_svim
;cmp ax, 0x3c00 ; f2 key
;je .f_key_pushed
cmp ax, 0x3c00 ; f2 key
je .f2_key_pushed
cmp ax, 0x3d00 ; f3 key
je .f3_key_pushed
cmp ax, 0x0e08 ; backspace
je .backspace_pushed
mov bx, ax
mov ax, 0xe20
mov al, bl
mov bx, [.buffer_for_svim_base]
add bx, [.buffer_counter_svim]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, [svim_counter_char_in_left_buffer]
mov [bx], al ; put char in the buffer
mov bx, [.buffer_counter_svim]
mov bx, [svim_counter_char_in_left_buffer]
add bx, 0x01
mov [.buffer_counter_svim], bx
mov [svim_counter_char_in_left_buffer], bx
int 0x10 ; print char
jmp .svim_loop
.end_svim:
;mov bx, [.buffer_for_svim_base]
;mov bx, [buffer_for_svim_base_left_of_cursor]
;add bx, svim_magic_buffer_size - 2
;mov [bx], ax
mov ax, [.fileindex_for_open_file]
mov bx, [.buffer_for_svim_base]
mov cx, [.buffer_counter_svim]
; When saving the file, we need to have all the data in the left buffer.
; So we loop through the right buffer and palce the data in the left.
mov ax, [svim_counter_char_in_right_buffer]
.copy_data_to_left_buffer:
cmp ax, 0
je .stop_copy
call handle_right_key_pressed
dec ax
jmp .copy_data_to_left_buffer
.stop_copy:
mov ax, [fileindex_for_open_file]
mov bx, [buffer_for_svim_base_left_of_cursor]
mov cx, [svim_counter_char_in_left_buffer]
mov dl, [svim_save_on_exit]
test dl, dl ; if zero qiut without exit
jz .svim_quit
call lsfs_write_file
.svim_quit:
call os_clear_screen
add sp, svim_magic_buffer_size
add sp, svim_magic_buffer_size
popa
ret
.f2_key_pushed:
mov al, 1
mov [svim_save_on_exit], al
call svim_redraw_window
jmp .svim_loop
.f3_key_pushed:
mov al, 0
mov [svim_save_on_exit], al
call svim_redraw_window
jmp .svim_loop
.backspace_pushed:
mov bx, [.buffer_counter_svim]
mov bx, [svim_counter_char_in_left_buffer]
cmp bx, 0
je .svim_loop
;print_format .debug_buffer_counter, bx
mov cx, bx
sub cx, 1
mov bx, [.buffer_for_svim_base]
sub cx , 1
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, cx
.delete_linebreak:
cmp BYTE [bx], 10
jne .delete_char
mov BYTE [bx], 0
mov [.buffer_counter_svim], cx
;print_format .debug_buffer_counter, cx
; Go back one space
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
int 0x10
; cx is already the counter
sub cx, 1 ; Substract one charecter from the buffer, CR and LF
sub bx, 1
mov BYTE [bx], 0
mov [svim_counter_char_in_left_buffer], cx
call svim_redraw_window
jmp .svim_loop
; Place a NULL
mov al, 0x0 ; NULL
.delete_char:
mov BYTE [bx], 0
mov [svim_counter_char_in_left_buffer], cx
call svim_redraw_window
jmp .svim_loop
handle_left_key_pressed:
pusha
mov ax, [svim_counter_char_in_left_buffer]
cmp ax, 0
je .end
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, ax
dec bx ; Because it faces the next free spot
mov dx, [bx]
mov BYTE [bx], 0
push dx
mov cx, [svim_counter_char_in_right_buffer]
mov bx, [buffer_for_svim_base_right_of_cursor]
add bx, cx
mov [bx], dx
inc bx
mov BYTE [bx], 0 ; be sure that the next byte is always zero
dec ax
inc cx
mov [svim_counter_char_in_left_buffer], ax
mov [svim_counter_char_in_right_buffer], cx
pop bx
cmp bx, 10 ; check if we hit a line break.
jne .end
call handle_left_key_pressed ; we have hit a linebreak and need to go once more
.end:
popa
ret
handle_right_key_pressed:
pusha
mov ax, [svim_counter_char_in_right_buffer]
cmp ax, 0 ; check if we have more on the right side of the buffer
je .end ; If we don't, jump to the end and do nothing.
mov bx, [buffer_for_svim_base_right_of_cursor]
add bx, ax
dec bx ; Because it faces the next free spot
mov dx, [bx]
mov BYTE [bx], 0
push dx
mov cx, [svim_counter_char_in_left_buffer]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, cx
mov [bx], dx
inc bx
mov BYTE [bx], 0 ; be sure that the next byte is always zero
dec ax
inc cx
mov [svim_counter_char_in_right_buffer], ax
mov [svim_counter_char_in_left_buffer], cx
pop bx
cmp bx, 13 ; check if we hit a line break.
jne .end
call handle_right_key_pressed ; we have hit a linebreak and need to go once more
.end:
popa
ret
handle_up_key_pressed:
call get_cursor_position ; Find the position of the cursor
xor cx, cx
mov cl, dl ; Store coulun count
push cx ; save the column count.
inc cx
.find_first_line_break:
cmp BYTE cl, 0
je .find_right_position_on_new_line
call handle_left_key_pressed
dec cl
jmp .find_first_line_break
.find_right_position_on_new_line:
call svim_get_left_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break
mov ax, [svim_get_cursor_distance_to_next_line_break]
pop cx
.move_curser_to_correct_position_on_the_new_line:
cmp cx, ax
jge .end
call handle_left_key_pressed
dec ax
jmp .move_curser_to_correct_position_on_the_new_line
.end:
ret
handle_down_key_pressed:
call get_cursor_position ; Find the position of the cursor
xor ax, ax
mov al, dl ; Store coulun count
push ax ; save the column count.
call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break
mov cx, [svim_get_cursor_distance_to_next_line_break]
.find_first_line_break:
cmp cx, 0
je .find_left_position_on_new_line
call handle_right_key_pressed
dec cx
jmp .find_first_line_break
.find_left_position_on_new_line:
call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break
mov ax, [svim_get_cursor_distance_to_next_line_break]
pop cx
cmp cx, ax
jle .move_curser_to_correct_position_on_the_new_line
mov cx, ax
.move_curser_to_correct_position_on_the_new_line:
cmp cx, 0
je .end
call handle_right_key_pressed
dec cx
jmp .move_curser_to_correct_position_on_the_new_line
.end:
ret
svim_get_left_line_count:
pusha
xor ax, ax ; Number of chars in the right side buffer
xor cx, cx ; This is our counter to the next line break
mov ax, [svim_counter_char_in_left_buffer]
mov bx, [buffer_for_svim_base_left_of_cursor]
add bx, ax
dec bx
.check_next:
cmp ax, 0 ; check if we have hit the absolut beginnig of the string
je .end
mov BYTE dl, [bx]
cmp BYTE dl, 10 ; See if we have hit an linebreak
je .end_line_break
dec bx ; dec one, to check the prev char, until we hit a line break.
dec ax
inc cx ; add one to the counter
jmp .check_next
.end_line_break:
;inc cx ; add one to the counter
.end:
mov WORD [svim_get_cursor_distance_to_next_line_break], cx
popa
ret
svim_get_right_line_count:
pusha
xor ax, ax ; Number of chars in the right side buffer
xor cx, cx ; This is our counter to the next line break
mov ax, [svim_counter_char_in_right_buffer]
mov bx, [buffer_for_svim_base_right_of_cursor]
add bx, ax
dec bx
.check_next:
cmp ax, 0 ; check if we have hit the absolut beginnig of the string
je .end
mov BYTE dl, [bx]
cmp BYTE dl, 13 ; See if we have hit an linebreak
je .end_line_break
dec bx ; dec one, to check the prev char, until we hit a line break.
dec ax
inc cx ; add one to the counter
jmp .check_next
.end_line_break:
inc cx ; add one to the counter
.end:
mov WORD [svim_get_cursor_distance_to_next_line_break], cx
popa
ret
get_cursor_position:
xor ax, ax
xor bx, bx
mov ah, 0x03
mov bh, 0x00 ; page number 0
int 0x10
ret
; Go back one space again as the above print of NULL pushes the cursor forward again.
mov ax, 0x0e08
svim_redraw_window:
call os_clear_screen
; move cursor to the bootom
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bh, 0x00 ; page number 0
mov dh, 0x17 ; row zero
mov dl, 0x00 ; coloumn zero
int 0x10
jmp .svim_loop
mov si, seperate_line
call print
mov si, welcome_svim
call print
;.f_key_pushed:
;mov al, 0x01 ;arg: index 1
;call os_change_screen
;jmp .svim_loop
mov al, [svim_save_on_exit]
test al, al
jz .not_save_mode
mov si, svim_string_save
jmp .after_not_safe_mode
.not_save_mode:
mov si, svim_string_not_save
.after_not_safe_mode:
call print
;.load_buffer_svim:
; move cursor to the top
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bh, 0x00 ; page number 0
mov dh, 0x00 ; row zero
mov dl, 0x00 ; coloumn zero
int 0x10
; Load from disk and, enter it, into the buffer
mov si, welcome_svim_select_file
call print
mov ax, [fileindex_for_open_file]
call dumpax10
call printCRLF
mov si, seperate_line
call print
ret
.debug_buffer_counter db 'Buffer count: %d', 13, 10, 0
.welcome_svim db 'Vim like text editor for SingOS, ESC to exit', 0
.welcome_svim_select_file db 'svim v0.0.5 - Open file: ', 0
.welcome_svim_enter_fileindex db 'Enter fileindex: ', 0
.seperate_line db '________________________________________________________________________________', 0
.fileindex_for_open_file dw 0
.buffer_for_svim_base dw 0
.buffer_counter_svim dw 0
svim_get_cursor_offset_on_current_line dw 0
svim_get_cursor_distance_to_next_line_break dw 0
buffer_for_svim_base_left_of_cursor dw 0
buffer_for_svim_base_right_of_cursor dw 0
svim_counter_char_in_left_buffer dw 0
svim_counter_char_in_right_buffer dw 0
seperate_line db '________________________________________________________________________________', 0
welcome_svim db 'Vim like text editor for SingOS, ESC to exit svim - ', 0
svim_string_save db 'save-mode', 0
svim_string_not_save db 'not-save-mode', 0
welcome_svim_select_file db 'svim v0.2.0 - Open file: ', 0
welcome_svim_enter_fileindex db 'Enter fileindex: ', 0
fileindex_for_open_file dw 0
svim_total_file_size_counter dw 0
svim_save_on_exit db 0

171
lib/xex.nasm

@ -0,0 +1,171 @@
; This is the "program" to execute a program
xex:
pusha ; save state before program
sub sp, 512
mov [.program_executable_buffer], sp
;mov [.program_executable_buffer], sp
call os_clear_screen
call lsfs_list_files_command
; move cursor to the bootom
xor ax, ax
xor bx, bx
mov ah, 0x02
mov bh, 0x00 ; page number 0
mov dh, 0x17 ; row zero
mov dl, 0x00 ; coloumn zero
int 0x10
mov si, .welcome_xex_enter_fileindex
call print
; Ask the user for the filename
xor bx, bx
xor cx, cx ; are going to be the counter
xor dx, dx
.enter_fileindex_loop:
push cx
.loop_no_push:
mov ax, 0x10 ; BIOS call to wait for key
int 0x16
cmp ax, 0x1c0d ; enter key
je .fileindex_done
cmp ax, 0x0e08 ; backspace
jne .no_enter_fileindex
cmp cx, 0
je .loop_no_push
pop cx
sub cx, 1
mov bx, [.program_executable_buffer]
add bx, cx
mov BYTE [bx], 0
; Go back one space
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
int 0x10
; Place a NULL
mov al, 0x0 ; NULL
int 0x10
; Go back one space again as the above print of NULL pushes the cursor forward again.
mov ax, 0x0e08
int 0x10
jmp .enter_fileindex_loop
.no_enter_fileindex:
mov bh, 0x00
mov bl, 0x02
mov ah, 0x0E
int 0x10 ; print char
pop cx
mov bx, [.program_executable_buffer]
add bx, cx
mov [bx], al
add cx, 1
; fileindex must only be 120 chars
cmp cx, 120
jae .fileindex_done
jmp .enter_fileindex_loop
.fileindex_done:
pop cx ; Cleanup, and now contain filename size
mov ax, cx
add ax, [.program_executable_buffer]
mov bx, ax
mov BYTE [bx], 0
mov si, [.program_executable_buffer]
call zstring_to_integer ; ax now contain the interger index for the file
mov [.fileindex_for_open_file], ax ; save the file index
mov ax, [.fileindex_for_open_file]
mov bx, [.program_executable_buffer]
.xex_lsfs_read_file:
; INPUT ax = file index
; INPUT bx = filebuffer
pusha ; save all register state
; We need to find the data pointers for the file.
push bx
mov dx, 24 ; LSFS_magic_start_sector
add ax, dx ; senctor number, into the master Table.
mov WORD [XEXPACK.db_addr_offset], xex_lsfs_loading_buffer
mov WORD [XEXPACK.lba_addr_dw_low], ax
mov WORD [XEXPACK.blkcnt], 0x1 ; Read to sectors, that is what the space is for the buffer in svim
mov WORD [XEXPACK.db_addr_segment], 0x50
mov si, XEXPACK ; address of "disk address packet"
mov ah, 0x42 ; READ
mov dl, [global_disk_identifier]
int 0x13
pop bx
; Save the buffer addr
mov bx, [xex_lsfs_loading_buffer + 288] ; this is the first data pointer
mov ax, bx
mov WORD [XEXPACK.lba_addr_dw_low], bx
mov WORD [XEXPACK.blkcnt], 0x4 ; Read to sectors, that is what the space is for the buffer in svim
mov WORD [XEXPACK.db_addr_segment], 0x2000
mov WORD [XEXPACK.db_addr_offset], 0x0
mov si, XEXPACK ; address of "disk address packet"
mov ah, 0x42 ; READ
mov dl, [global_disk_identifier]
int 0x13
popa
mov ax, [xex_lsfs_loading_buffer + 264]
; I guess we should have something like
push cs ; this gives us the correct code segment for the kernel
push .this_place ; this gives the correct adress to come back from the program.
push 0x2000
push 0x0
;push 0x0050
;push 0x0512
mov ax, 0x2000
mov ds, ax ; move data segment to the program start
retf
.this_place:
push ax
mov ax, 0x50
mov ds, ax ; Back to the kernel space
call printCRLF
mov si, .program_output_text
call print
pop ax
call dumpax
;mov bx, ss
;call bx:ax ; here. We want to execute the file that we just have benn loaded in memory
; The executable should make use of the global systemcall table.
; That is what we are trying to get to work here.
add sp, 512
popa ; retore
ret
.welcome_xex_enter_fileindex db 'Enter program index to execute: ', 0
.program_output_text db 'Program has terminated with return value: ', 0
.fileindex_for_open_file dw 0
.program_executable_buffer dw 0
align 2
xex_lsfs_loading_buffer times 512 db 0
XEXPACK:
.dap_Size: db 0x10 ; This is always 16 bytes (0x10)
.rev_byte: db 0x0 ; reserved byte, should always be zero
.blkcnt: dw 0x0 ; int 13 resets this to # of blocks actually read/written
.db_addr_offset: dw 0x0 ; memory buffer destination address (0:7c00)
.db_addr_segment: dw 0x0 ; in memory page zero
.lba_addr_dw_low: dd 0x0 ; put the lba to read in this spot
.lba_addr_dw_high: dd 0x0 ; more storage bytes only for big lba's ( > 4 bytes )

389
vbr.nasm

@ -1,162 +1,196 @@
ORG 0x7c00
BITS 16
%define DISK_SERVICE 0x0050:0x0256
%define KERNEL 0x0050:0x0512
%define DISK_SERVICE 0x0050:0x0000
%define KERNEL 0x2500:0x0000 ;0x0050:0x0512
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vbr_lfsf:
; Volume Boot Record
; This will start SingOS from the disk
; The disk format has to be LessSimpleFileSystem
; Loading /kernel/kernel.bin which should contain the kernel for the system
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Ensure that the data segment and extra segment is set to 0x00
mov ax, 0x00
mov ds, ax
mov es, ax
; loading essentials for SingOS to run
; Setup stack
mov ax, 0x8fc0
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack
mov bp, sp
mov [global_disk_identifier], dl ; saving disk_identifier, this is the number the disk that we are booting from.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SYSTEM CALL TABLE STARTING AT POSITION 0x0050:0x0000
; To already support 64-bit, the entries is 64-bit
; But in 16-bit, the adresses is only 16-bit
; These are stored in the first 16-bits
; There is reserved 2 sectors to the table witch means that we have room for
; 128 System Calls
; |----|----------------------------------------------------------------------------|
; | 1 | Master Table| call [0x0050:0x0000] Pointer to the Master File Table |
; |----|----------------------------------------------------------------------------|
; | 2 | FILE SYSTEM | call [0x0050:0x0008] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 3 | OS_LIB | call [0x0050:0x0016] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 1 | FILE SYSTEM | call [0x0050:0x0000] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
; | 2 | OS_LIB | call [0x0050:0x0008] for arguments see under the file system |
; |----|----------------------------------------------------------------------------|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [vbr_disk_identifier], dl ; saving disk_identifier, this is the number the disk that we are booting from.
; This number is set by the bios
xor ax, ax
mov al, dl
mov al, [vbr_disk_identifier]
mov [vbr_lba_position_at_disk], ax ; From the MBR we need information of where we are located at the disk.
; If this fails, we could lookup our self, in the MBR where we are located.
;mov ax, 0x50
;mov cs, ax
;mov ds, ax
;mov ax, 0x8fc0
;mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
;mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack
;mov bp, sp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The system has to support int13 bios extended system calls, otherwise is SingOS not supporting the hardware.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ah, 0x41 ;Set AH = 0x41
mov bx, 0x55aa ;BX = 0x55AA
mov dl, [vbr_disk_identifier] ;DL = disk_id
int 0x13 ;Issue an INT 0x13.
jc .is_not_supported
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The system is suportted
; We are now loading the filesystem
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;mov WORD bx, [vbr_lba_position_at_disk]
mov WORD [DAPACK.lba_addr_dw_low], 89
mov WORD [DAPACK.blkcnt], 0x08 ; Read to sectors, that is what the space is for the buffer in svim
mov WORD [DAPACK.db_addr_segment], 0x50
mov WORD [DAPACK.db_addr_offset], 0x256
mov si, DAPACK ; address of "disk address packet"
mov ah, 0x42 ; READ
mov dl, [vbr_disk_identifier]
int 0x13
;call dumpax
;call DISK_SERVICE
mov [vbr_disk_identifier], dl
mov al, dl
;call DISK_SERVICE
;mov ax, 0
;mov ah, 0x10
;int 0x16
;mov ah, 0x0e
;mov al, 66 ; backspace
;int 0x10 ; print char
mov dl, [global_disk_identifier] ;DL = disk_id
int 0x13 ;Issue an INT 0x13.
jnc ext_disk_supported
; The System does support exented read write
mov si, vbr_lsfs_disk_error_msg
call 0x00:tmp_print
cli
hlt
;call DISK_SERVICE
;Routine for printing a 'ax' as hex
;tmp_dumpax:
;pusha ; save registers
;mov bx, ax
;mov ah, 0xE ; Teletype output
;mov cx, 4 ; 4 nipples in a 16 bit word
;.loop:
;rol bx, 4 ; rotate to next nipple
;mov al, bl ; we copy to al because we need to mask only the low 4 bits
;and al, 1111b ; Do the masking
;add al, '0' ; convert to ASCII
;cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A'
;jbe .skip ; -|-
;add al, 7 ; -|-
;.skip: ; -|-
;int 0x10 ; BIOS call 'output'
;loop .loop
;popa ; restore registers
;retf
tmp_print:
; Prints string in si
; IN si: zero terminated string to print
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;mov ax, 0x7e55
;mov ax, si
;call 0x00:tmp_dumpax
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
.printchar:
lodsb ; Load byte at address SI into AL, and increment SI
test al, al
jz .done ; If the character is zero (NUL), stop writing the string
int 0x10 ; Otherwise, print the character via 'int 0x10'
jmp .printchar ; Repeat for the next character
.done:
retf
;mov ax, 0
;mov ah, 0x10
;int 0x16
;mov ah, 0x0e
;mov al, 66 ; backspace
;int 0x10 ; print char
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The disk service is now loaded.
; Now we are going to load the Master table.
;
; We are now loading the filesystem
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov WORD [DAPACK.lba_addr_dw_low], 97
mov WORD [DAPACK.blkcnt], 0x1f
mov WORD [DAPACK.db_addr_segment], 0x50
mov WORD [DAPACK.db_addr_offset], 0x0512
; loading essentials for SingOS to run
; starting by loading the rest of the VBR:
ext_disk_supported:
mov si, vbr_message
call 0x00:tmp_print
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The system is suportted
; We are now loading the kernel "/kernel/kernel.bin"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INPUT
; ax = sector index for the FSCI that has to be loaded.
; bx = segment
;mov ax, [vbr_LBA_FSCI]
;mov bx, 0x00
;call lsfs_load_fsci_info;
;INPUT
; ax = filename
; bx = pointer to buffer
; cx = buffer_size
; dx = offset in file
; es = segment to read in data
;call lsfs_read_file
; RETURN
; ax preserved
; bx preserved
; cx preserved
; dx data read
; es = remember to restore es if this has to be saved.
mov ax, [vbr_LBA_address]
inc ax
mov dl, [global_disk_identifier]
mov WORD [DAPACK.lba_addr_dw_low], ax
mov WORD [DAPACK.blkcnt], 0x10
mov WORD [DAPACK.db_addr_segment], 0x7e0
mov WORD [DAPACK.db_addr_offset], 0x00
mov si, DAPACK ; address of "disk address packet"
mov ah, 0x42 ; READ
mov dl, [vbr_disk_identifier]
mov dl, [global_disk_identifier]
int 0x13
;call dumpax
xor ax, ax
mov dl, [vbr_disk_identifier]
mov al, dl
;call dumpax
mov dl, [vbr_disk_identifier]
jmp KERNEL
mov cx, [vbr_LBA_FSCI]
mov bx, ds
mov ax, 0x1
push cx
push bx
push ax
mov cx, 0x7e0
mov ds, cx
mov es, cx
call 0x7e0:0x00
add sp, 0x6 ; skip the paramerts
mov cx, 0x0
mov ds, cx
mov es, cx
; Set the Parameter_Struct
mov ax, lsfs_path
mov [Parameter_Struct.path], ax
mov WORD [Parameter_Struct.buffer_segment], 0x50
mov WORD [Parameter_Struct.buffer_address], 0x00
mov WORD [Parameter_Struct.buffer_size], 0xFFFF
mov WORD [Parameter_Struct.byte_offset_into_file], 0x00
mov cx, Parameter_Struct
mov bx, ds
mov ax, 0x2
push cx
push bx
push ax
mov cx, 0x7e0
mov ds, cx
mov es, cx
call 0x7e0:0x00
add sp, 0x6 ; skip the paramerts
mov cx, 0x0
mov ds, cx
mov es, cx
; Set the Parameter_Struct
mov ax, kernel_path
mov [Parameter_Struct.path], ax
mov WORD [Parameter_Struct.buffer_segment], 0x2500
mov WORD [Parameter_Struct.buffer_address], 0x00
mov WORD [Parameter_Struct.buffer_size], 0xFFFF
mov WORD [Parameter_Struct.byte_offset_into_file], 0x00
mov cx, Parameter_Struct
mov bx, ds
mov ax, 0x2
push cx
push bx
push ax
mov cx, 0x7e0
mov ds, cx
mov es, cx
call 0x7e0:0x00
add sp, 0x6 ; skip the paramerts
mov cx, 0x0
mov ds, cx
mov es, cx
; ready to jump to the kernel
mov bx, [vbr_LBA_FSCI]
mov dl, [global_disk_identifier]
jmp KERNEL
nop
cli
hlt
.is_not_supported:
; The System does support exented read write
mov si, lsfs_disk_error_msg
;call print
;Routine for printing a 'ax' as hex
dumpax:
pusha ; save registers
mov bx, ax
mov ah, 0xE ; Teletype output
mov cx, 4 ; 4 nipples in a 16 bit word
.loop:
rol bx, 4 ; rotate to next nipple
mov al, bl ; we copy to al because we need to mask only the low 4 bits
and al, 1111b ; Do the masking
add al, '0' ; convert to ASCII
cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A'
jbe .skip ; -|-
add al, 7 ; -|-
.skip: ; -|-
int 0x10 ; BIOS call 'output'
loop .loop
popa ; restore registers
ret
vbr_disk_identifier db 0
vbr_lba_position_at_disk dw 0
lsfs_disk_error_msg db 'The system does not support disk operations,', 13, 10, 0
DAPACK:
.dap_Size: db 0x10 ; This is always 16 bytes (0x10)
.rev_byte: db 0x0 ; reserved byte, should always be zero
@ -166,61 +200,32 @@ DAPACK:
.lba_addr_dw_low: dd 0x0 ; put the lba to read in this spot
.lba_addr_dw_high: dd 0x0 ; more storage bytes only for big lba's ( > 4 bytes )
times 4096-($-$$) db 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HERE START THE FILE SYSTEM
; This is the Master Table
; This is the fixed entries when the system is compilet
; DEFAULT SIZE IS 64 FILES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Entry one:
;.filename:
db 'File_System_Control_information', 0
times 224 db 0
;.file_id:
dw 0x0, 0x0, 0x0, 0x00 ; 64-bits
;.file_size
dw 512, 0x0, 0x0, 0x0 ; 64-bits Should be the actual number of bytes.
;.ext_file_data 64-bits (Extended data about the file, timestamps etc.)
dw 0x0, 0x0, 0x0, 0x0
;control_bits 64-bits
dw 0x0, 0x0, 0x0, 0x0
;.file_data_pointers
dw 88, 0x0, 0x0, 0x0
times 216 db 0
; Entry Two:
db 'LessSimpelFileSystem', 0
times 235 db 0
;.file_id:
dw 0x01, 0x0, 0x0, 0x0
;.file_size
dw 4096, 0x0, 0x0, 0x0
;.ext_file_data 64-bits (Extended data about the file, timestamps etc.)
dw 0x0, 0x0, 0x0, 0x0
;control_bits 64-bits
dw 0x0, 0x0, 0x0, 0x0
;.file_data_pointers
dw 89, 0x0, 0x0, 0x0
times 216 db 0
; Entry Three:
db 'kernel', 0
times 249 db 0
;.file_id:
dw 0x02, 0x0, 0x0, 0x0
;.file_size
dw 0x00, 0x10, 0x0, 0x0
;.ext_file_data 64-bits (Extended data about the file, timestamps etc.)
dw 0x0, 0x0, 0x0, 0x0
;control_bits 64-bits
dw 0x0, 0x0, 0x0, 0x0
;.file_data_pointers
dw 97, 0x0, 0x0, 0x0
times 216 db 0
times 4096 + (32768-($-$$)) db 0
Parameter_Struct:
.path dw 0x00 ; char*
.new_path dw 0x00 ; char*
.buffer_segment dw 0x00 ; int
.buffer_address dw 0x00 ; int
.buffer_size dw 0x00 ; int
.data_length dw 0x00 ; int
.byte_offset_into_file dw 0x00 ; int
.entry_kind dw 0x00 ; Table_Entry_Kind
global_disk_identifier db 0
vbr_message db 'VBR: Less Simple File System', 13, 10, 'Loading system', 13, 10, 0
vbr_lsfs_disk_error_msg db 'The system does not support disk operations', 0
lsfs_path db '/kernel/utils/lsfs.bin', 0
kernel_path db '/kernel/kernel.bin', 0
times 446-($-$$) db 0
vbr_size_in_bytes dw 0x00, 0x00, 0x00, 0x00 ; size of the VBR in secotrs (Such that we can load the rest of the VBR)
vbr_LBA_address dw 0x00, 0x00, 0x00, 0x00 ; Abselout LBA adress of this VBR, such that we know where to find the FSCI (offset 1MB)
vbr_LBA_FSCI dw 0x00, 0x00, 0x00, 0x00
times 510-($-$$) db 0
dw 0x1818; Signature, homemade, sshould it be 0xAA55?
; rest of VBR, which has to be loaded in the first part of the VBR
;%include "filesystems/lsfs/lsfs.nasm"
incbin "../lsfs_16-bit/disk.out"
; By specification the max size can be 1MB of the compiled file.
Loading…
Cancel
Save