Skip to content

Commit

Permalink
Improve installation and documentation (#73)
Browse files Browse the repository at this point in the history
* Add kernel::fs::mount

* Check if fs is mounted before opening dir

* Save password hash during user creation

* Create home directory during user creation

* Improve path checking in mkfs

* Improve mkfs output

* Add install command

* Check presence of username and password during user creation

* Update documentation

* Check if user already exists before creation

* Split hashed_password

* Add save_hashed_password

* Rename login command to user

* Display MOROS version in a consistent way

* Use ctrl+d instead of ctrl+c to exit shell

* Rename mkfs to disk format

* Add disk list command

* Change prompt color if last command errored

* Improve installer

* Use $ and > prompts in doc

Use $ and > prompts in doc to indicate commands outside and inside
of MOROS respectively.
  • Loading branch information
vinc authored Jul 5, 2020
1 parent ac390fb commit c9d56e6
Show file tree
Hide file tree
Showing 16 changed files with 503 additions and 233 deletions.
37 changes: 22 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project started from the [seventh post][1] of the second edition of

![screenshot](screenshot.png)


## Features

- [x] External bootloader (using [bootloader](https://github.com/rust-osdev/bootloader))
Expand All @@ -34,39 +35,45 @@ This project started from the [seventh post][1] of the second edition of
- [ ] Multitasking
- [ ] A real userspace


## Setup

Install tools:

curl https://sh.rustup.rs -sSf | sh
rustup install nightly
rustup default nightly
rustup component add rust-src
rustup component add llvm-tools-preview
cargo install cargo-xbuild bootimage
$ curl https://sh.rustup.rs -sSf | sh
$ rustup install nightly
$ rustup default nightly
$ rustup component add rust-src
$ rustup component add llvm-tools-preview
$ cargo install cargo-xbuild bootimage


## Usage

Build image:
Build image to `disk.img`:

make image output=vga keyboard=qwerty
$ make image output=vga keyboard=qwerty

Run on QEMU:

make qemu output=vga

MOROS will open a console in diskless mode after boot if no filesystem is
detected. Use `mkfs /dev/ata/0/0` to create a filesystem on the ATA hard drive
that will be used on the next boot.
$ make qemu output=vga

Run on a native x86 computer by copying the bootloader and kernel to a hard
drive or USB stick (but there is currently no USB driver so the filesystem
will not be available):

sudo dd if=target/x86_64-moros/release/bootimage-moros.bin of=/dev/sdx && sync
$ sudo dd if=target/x86_64-moros/release/bootimage-moros.bin of=/dev/sdx && sync

In both cases, MOROS will open a console in diskless mode after boot if no
filesystem is detected. The following command will setup the filesystem on the
first hard drive of the first ATA bus, allowing you to exit the diskless mode
and log in as a normal user:

> install

**Be careful not to overwrite the hard drive of your OS when using `dd` inside
your OS or `mkfs` inside MOROS.**
your OS, and `install` or `disk format` inside MOROS.**


## LICENSE

Expand Down
140 changes: 113 additions & 27 deletions doc/filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,83 @@

## Hard drive

A hard drive is separated in block of 512 bytes, grouped into three areas. The
first is reserved for future uses, the second is used as a bitmap mapping the
allocated blocks in the third area. The data stored on the hard drive use the
blocks of the third area.

During the first boot of the OS, the root dir will be allocated, using the
first block of the data area.
A hard drive is separated in blocks of 512 bytes, grouped into 4 areas:

+------------+
| Boot | (2048 blocks)
+------------+
| Superblock | (2 blocks)
+------------+
| Bitmap | (512 blocks)
+------------+
| Data |
+------------+

The first area contains the bootloader and the kernel, the second is a
superblock with a magic string to identify the file system, the third is a
bitmap mapping the allocated data blocks of the last area.

A location on the tree of dirs and files is named a path:

- The root dir is represented by a slash: `/`
- A dir inside the root will have its name appended to the slash: `/usr`
- Subsequent dirs will append a slash and their names: `/usr/admin`


### Creation with QEMU

$ qemu-img create disk.img 128M
Formatting 'disk.img', fmt=raw size=134217728


### Setup in diskless console

During boot MOROS will detect the hard drives present on the ATA buses, then
the filesystems on those hard drives. If no filesystem is found, MOROS will
open a console in diskless mode to allow the user to create one with the `mkfs`
command:
During boot MOROS will detect any hard drives present on the ATA buses, then
look for a filesystem on those hard drives. If no filesystem is found, MOROS
will open a console in diskless mode to allow the user to create one with
the `disk format` command:

> disk format /dev/ata/0/0

This command will format the first disk on the first ATA bus by writing a magic
string in a superblock, mounting the filesystem, and allocating the root
directory.

The next step during setup is to create the directory structure:

> write /bin/ # Binaries
> write /dev/ # Devices
> write /ini/ # Initialisation files
> write /lib/ # Libraries
> write /net/ # Network
> write /src/ # Sources
> write /tmp/ # Temporary files
> write /usr/ # User directories
> write /var/ # Variable files

Then the following should be added to the boot script with the
command `edit /ini/boot.sh` to allow MOROS to finish booting:

> mkfs /dev/ata/0/0
user login
shell

Finally a user can be created with the following command:

> user create

All of this can be made more easily by running the `install` command instead.
This installer will also add additional files contained in the `dsk`
repository of the source code, like a nice login banner :)


## Data Structures

## Data

### BlockBitmap

Bitmap of allocated blocks in the data area.


### Block

A block is small area of 512 bytes on a hard drive, and it is also part of
Expand All @@ -44,28 +87,71 @@ linked list representing a file or a directory.
The first 4 bytes of a block is the address of the next block on the list and
the rest of block is the data stored in the block.

Structure:

0
0 1 2 3 4 5 6 n
+-+-+-+-+-+-+-+ // +-+
| addr | data |
+-+-+-+-+-+-+-+ // +-+

n = 512


### DirEntry

A directory entry represent a file or a directory contained inside a directory.
Each entry use a variable number of bytes that must fit inside the data of one
block. Those bytes represent the kind of entry (file or dir), the address of
the first block, the filesize (max 4GB), and the filename (max 255 chars) of
the entry.
A directory entry represents a file or a directory contained inside a
directory. Each entry use a variable number of bytes that must fit inside the
data of one block. Those bytes represent the kind of entry (file or dir), the
address of the first block, the filesize (max 4GB), the length of the filename,
and the filename (max 255 chars) of the entry.

Structure:

- 0..1: kind
- 1..5: addr
- 5..10: size
- 10..11: name len
- 11..n: name buf
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 m
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+
|k| addr | size |n| name buffer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+

k = kind of entry
n = length of name buffer
m = 9 + n


### Dir

A directory contains the address of the first block where its directory entries
are stored.
The first block of a directory contains the address of the next block where its
directory entries are stored and the first entries in the rest of the block.

If all entries can fit into one block the address of the next block will be
empty.

Structure:

0 1
0 1 2 3 4 5 6 7 8 9 0 n
+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+ // +-+
| addr | dir entry 1 | dir entry 2 |
+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+ // +-+

n = 512


### File

A file contains the address of its first block along with its filesize and
filename, and a reference to its parent directory.
The first block of a contains the address of the next block where its contents
is stored and the beginning of its contents in the rest of the block.

If all contents can fit into one block the address of the next block will be
empty.

Structure:

0
0 1 2 3 4 5 6 7 8 n
+-+-+-+-+-+-+-+-+-+ // +-+
| addr | contents |
+-+-+-+-+-+-+-+-+-+ // +-+

n = 512
Loading

0 comments on commit c9d56e6

Please sign in to comment.