Skip to content

Commit

Permalink
Merge branch 'master' of github.personal:NANO-DEV/NANO-S16
Browse files Browse the repository at this point in the history
  • Loading branch information
jonlinper committed Feb 20, 2017
2 parents 8a637c0 + 5ff1a89 commit f3fb055
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 65 deletions.
59 changes: 55 additions & 4 deletions README.md
Expand Up @@ -17,7 +17,7 @@ System requirements:
The building process is expected to be executed in a Linux system. In Windows 10 it can be built using Windows Subsystem for Linux.

1. Install required software:
* make, gcc, bcc, nasm and ld86 to build the OS and user programs
* make, gcc, bcc, nasm and ld86 to build the operating system and user programs
* optionally install qemu x86 emulator to test the images in a virtual machine
* optionally install exuberant-ctags to generate tags
* optionally use dd to write disk images on storage devices
Expand All @@ -33,9 +33,17 @@ The building process is expected to be executed in a Linux system. In Windows 10
3. Build: Customize `Makefile` and `source/Makefile` files. Run `make` from the root directory to build everything. Images will be generated in the `images` directory.

##Testing
After building, run `make qemu` (linux) or `qemu.bat` (windows) from the root directory to test the OS in a virtual machine.
After building, run `make qemu` (linux) or `qemu.bat` (windows) from the root directory to test the operating system in qemu. Other virtual machines have been successfully tested. To test the system using VirtualBox, create a new `Other/DOS` machine and start it with `images/os_fd.img` as floppy image.

The system can operate real hardware if images are written to physical disks.
If debug mode is activated in the operating system configuration, it will output debug information through the first serial port in real time. This can be useful for system and user application developers. This serial port is configured to work at 2400 bauds, 8 data bits, odd parity and 1 stop bit.

Using the provided qemu scripts, the serial port will be automatically mapped to the process standard input/output. For VirtualBox users, it is possible for example to telnet from putty if COM1 is set to TCP mode without a pipe, and the same port if specified in both programs.

The system can operate real hardware if images are written to physical disks. Writing images to disks to test them in real hardware is dangerous and can cause loss of data or boot damage, among other undesired things, in all involved computers. So, it is not recommended to proceed unless this risk is understood and assumed. To write images to physical disks, `dd` can be used in linux:
```
dd status=noxfer conv=notrunc if=images/os-fd.img of=/dev/sdb status=none
```
Replace `/dev/sdb` with the actual target storage device. Usually `root` privileges will be needed to run this command.

##User manual
A system disk is needed to start the OS for first time. See later sections for information about how to install (clone system) once it is running.
Expand Down Expand Up @@ -76,6 +84,15 @@ clone hd0
####CLS
Clear the screen.

####CONFIG
Show or set configuration parameter values. To show current values, call it without arguments. To set values, two parameters are expected: the parameter name to set, and its value.

Example:
```
config
config debug enabled
```

####COPY
Copy files. Two parameters are expected: the path of the file to copy, and the path of the new copy.

Expand All @@ -99,7 +116,7 @@ Show basic help.
Show system version and hardware information.

####LIST
List the contents of a directory. One parameter is expected: the path of the directory to list.
List the contents of a directory. One parameter is expected: the path of the directory to list. If this parameter is omitted, the contents of the system disk root directory will be listed.

Example:
```
Expand Down Expand Up @@ -132,3 +149,37 @@ read documents/doc.txt

####TIME
Show current date and time.


##User programs development

The easiest way to develop new user programs is:

1. Setup the development system so it contains a copy of the full source tree and it's able to build and test it. See the building and testing pages.

2. Create a new `programname.c` file in `source/programs` folder with this code:

```
/*
* User program: programname
*/
#include "types.h"
#include "ulib/ulib.h"
uint main(uint argc, uchar* argv[])
{
return 0;
}
```

3. Edit this line of `source/Makefile` and add `$(PROGDIR)programname.bin` at the end, like this:
```
programs: $(PROGDIR)edit.bin $(PROGDIR)programname.bin
```
4. Edit this line of `Makefile` and add `$(SOURCEDIR)programs/programname.bin` at the end, like this:
```
USERFILES := $(SOURCEDIR)programs/edit.bin $(SOURCEDIR)programs/programname.bin
```
5. Add code to `programname.c`. See all available system functions in `ulib/ulib.h`
6. Build and test
18 changes: 8 additions & 10 deletions source/boot/boot.s
Expand Up @@ -36,27 +36,25 @@ start:
mov eax, 0
mov ax, 1

mov bx, (STAGE_LOC>>4)
mov es, bx

.read_next:
push ax
call disk_lba_to_hts

mov bx, 0
mov es, bx
mov bx, [BUFFER]

mov ah, 2
mov al, 1

pusha ; Prepare to enter loop
pusha

.read_loop:
push es
pop es

popa
pusha

stc ; A few BIOSes do not set properly on error
stc ; Some BIOSes do not set properly on error
int 13h ; Read sectors

jnc .read_finished
Expand All @@ -72,9 +70,9 @@ start:
cmp ax, 1
jne .inc_loop ; If it was the super block
mov bx, [BUFFER]
mov ax, [bx+12]
mov ax, [es:bx+12]
mov bx, ax
add bx, 64
add bx, 72
mov [LASTBLOCK], bx
jmp .read_next ; find where the bootable image starts
.inc_loop:
Expand Down Expand Up @@ -131,7 +129,7 @@ disk_lba_to_hts:

SECTORS dw 18
SIDES dw 2
BUFFER dw STAGE_LOC
BUFFER dw 0
LASTBLOCK dw 240

error:
Expand Down
28 changes: 14 additions & 14 deletions source/fs.c
Expand Up @@ -134,12 +134,12 @@ static uint read_disk(uint disk, uint block, uint offset, uint buff_size, uchar*

/* Check params */
if(buff == 0) {
sputstr("Read disk: bad buffer\n\r");
debugstr("Read disk: bad buffer\n\r");
return 1;
}

if(disk_info[disk_to_index(disk)].size == 0) {
sputstr("Read disk: bad disk\n\r");
debugstr("Read disk: bad disk\n\r");
return 1;
}

Expand Down Expand Up @@ -174,7 +174,7 @@ static uint read_disk(uint disk, uint block, uint offset, uint buff_size, uchar*

/* Handle DMA access 64kb boundary. Read sector by sector */
if(result == 0x900) {
sputstr("Read disk: DMA access accross 64Kb boundary. Reading sector by sector\n\r");
debugstr("Read disk: DMA access accross 64Kb boundary. Reading sector by sector\n\r");
for(; n_sectors > 0; n_sectors--) {
result = read_disk_sector(disk, sector, 1, aux_buff);
if(result != 0) {
Expand All @@ -201,7 +201,7 @@ static uint read_disk(uint disk, uint block, uint offset, uint buff_size, uchar*
}

if(result != 0) {
sputstr("Read disk error (%x)\n\r", result);
debugstr("Read disk error (%x)\n\r", result);
}

return result;
Expand All @@ -221,12 +221,12 @@ static uint write_disk(uint disk, uint block, uint offset, uint buff_size, uchar

/* Check params */
if(buff == 0) {
sputstr("Write disk: bad buffer\n\r");
debugstr("Write disk: bad buffer\n\r");
return 1;
}

if(disk_info[disk_to_index(disk)].size == 0) {
sputstr("Write disk: bad disk\n\r");
debugstr("Write disk: bad disk\n\r");
return 1;
}

Expand Down Expand Up @@ -261,7 +261,7 @@ static uint write_disk(uint disk, uint block, uint offset, uint buff_size, uchar
result += write_disk_sector(disk, sector, n_sectors, &buff[i]);
/* Handle DMA access 64kb boundary. Write sector by sector */
if(result == 0x900) {
sputstr("Write disk: DMA access accross 64Kb boundary. Writting sector by sector\n\r");
debugstr("Write disk: DMA access accross 64Kb boundary. Writting sector by sector\n\r");
for(; n_sectors > 0; n_sectors--) {
memcpy(aux_buff, &buff[i], SECTOR_SIZE);
result = write_disk_sector(disk, sector, 1, aux_buff);
Expand Down Expand Up @@ -289,7 +289,7 @@ static uint write_disk(uint disk, uint block, uint offset, uint buff_size, uchar
}

if(result != 0) {
sputstr("Write disk error (%x)\n\r", result);
debugstr("Write disk error (%x)\n\r", result);
}

return result;
Expand Down Expand Up @@ -342,7 +342,7 @@ void fs_init_info()

/* For each disk */
for(disk_index=0; disk_index<MAX_DISK; disk_index++) {
sputstr("Check filesystem in %x: ", index_to_disk(disk_index));
debugstr("Check filesystem in %x: ", index_to_disk(disk_index));

/* If hardware related disk info is valid */
if(disk_info[disk_index].size != 0) {
Expand All @@ -353,7 +353,7 @@ void fs_init_info()
if(sb.type == SFS_TYPE_ID) {
disk_info[disk_index].fstype = FS_TYPE_NSFS;
disk_info[disk_index].fssize = sb.size;
sputstr("NSFS\n\r");
debugstr("NSFS\n\r");
continue;
}
}
Expand All @@ -362,7 +362,7 @@ void fs_init_info()
disk_info[disk_index].fstype = FS_TYPE_UNKNOWN;
disk_info[disk_index].fssize = 0;
}
sputstr("unknown\n\r");
debugstr("unknown\n\r");
}
}

Expand Down Expand Up @@ -1536,7 +1536,7 @@ uint fs_format(uint disk)
uint32_t disk_size;
uint disk_index = disk_to_index(disk);

sputstr("format disk: %x (system_disk=%x)\n\r", disk, system_disk);
debugstr("format disk: %x (system_disk=%x)\n\r", disk, system_disk);

/* Copy boot block from system disk to target disk */
result = read_disk(system_disk, 0, 0, BLOCK_SIZE, buff);
Expand Down Expand Up @@ -1572,7 +1572,7 @@ uint fs_format(uint disk)
if(result != 0) {
return ERROR_IO;
}
sputstr("format: %x blocks=%U entries=%U boot=%U\n\r", disk, sb->size, sb->nentries, sb->bootstart);
debugstr("format: %x blocks=%U entries=%U boot=%U\n\r", disk, sb->size, sb->nentries, sb->bootstart);

nentries = (uint)sb->nentries;

Expand Down Expand Up @@ -1615,7 +1615,7 @@ uint fs_format(uint disk)
strcat_s(k_dst_path, PATH_SEPARATOR_S, sizeof(k_dst_path));
strcat_s(k_dst_path, entry->name, sizeof(k_dst_path));

sputstr("format: copy %s %s\n\r", k_src_path, k_dst_path);
debugstr("format: copy %s %s\n\r", k_src_path, k_dst_path);

result = fs_copy(k_src_path, k_dst_path);
if(result >= ERROR_ANY) {
Expand Down
4 changes: 4 additions & 0 deletions source/hw86.h
Expand Up @@ -34,6 +34,10 @@ extern void io_out_char_attr(uint x, uint y, uchar c, uchar attr);
* Send a character to the serial port
*/
extern void io_out_char_serial(uchar c);
/*
* Read a character from the serial port
*/
extern uchar io_in_char_serial();
/*
* Hide the cursor
*/
Expand Down
33 changes: 30 additions & 3 deletions source/hw86.s
Expand Up @@ -152,11 +152,11 @@ _io_out_char_serial:

test byte [_serial_status], 0x80
jne .skip
mov dx, 0
mov dx, 0 ; Port number
mov bx, sp ; Save the stack pointer
mov al, [bx+8] ; Get char from string
mov ah, 01h ; int 14h n
int 0x14 ; Print it
mov ah, 01h ; int 14h ah=01h: write
int 0x14 ; Send it

mov byte [_serial_status], ah

Expand All @@ -166,6 +166,33 @@ _io_out_char_serial:
pop bx
ret

;
; uchar io_in_char_serial();
; Read a char from serial port
;
global _io_in_char_serial
_io_in_char_serial:
push dx
push ax

test byte [_serial_status], 0x80
jne .skip
mov dx, 0 ; Port number
mov al, 0
mov ah, 02h ; int 14h ah=02h: read
int 0x14 ; Get it

;mov byte [_serial_status], ah
test byte ah, 0x80
mov ah, 0
je .skip
mov ax, 0

.skip:
pop dx
pop dx
ret

extern _serial_status

;
Expand Down

0 comments on commit f3fb055

Please sign in to comment.