├── .gitignore
├── README.md
└── calc_os
├── .cargo
└── config.toml
├── .idea
├── .gitignore
├── calc_os.iml
├── modules.xml
└── vcs.xml
├── Cargo.toml
├── help_os.txt
├── qemu-system-x86_64
├── rust-toolchain.toml
├── src
├── main.rs
└── vga_buffer.rs
└── x86_64-blog_os.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | debug/
4 | target/
5 |
6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8 | Cargo.lock
9 |
10 | # These are backup files generated by rustfmt
11 | **/*.rs.bk
12 |
13 | # MSVC Windows builds of rustc generate these, which store debugging information
14 | *.pdb
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CalcOS
2 | 
3 |
4 | - first boot on qemu emulator
5 |
--------------------------------------------------------------------------------
/calc_os/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [unstable]
2 | build-std-features = ["compiler-builtins-mem"]
3 | build-std = ["core", "compiler_builtins"]
4 |
5 | [build]
6 | target = "x86_64-blog_os.json"
7 |
8 | [target.'cfg(target_os = "none")']
9 | runner = "bootimage runner"
--------------------------------------------------------------------------------
/calc_os/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/calc_os/.idea/calc_os.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/calc_os/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/calc_os/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/calc_os/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "calc_os"
3 | version = "0.1.0"
4 | authors = ["dazai"]
5 |
6 | [dependencies]
7 | bootloader = "0.9.23"
8 | volatile = "0.5.1"
--------------------------------------------------------------------------------
/calc_os/help_os.txt:
--------------------------------------------------------------------------------
1 | // DOCUMENTATION
2 | https://os.phil-opp.com/freestanding-rust-binary/#introduction
3 |
4 | // COMMANDS
5 | rustup target add thumbv7em-none-eabihf
6 | cargo build --target thumbv7em-none-eabihf
7 |
8 | qemu-system-x86_64 -drive format=raw,file=bootimage-calc_os.bin / cargo run // heh
9 | cargo run
10 |
11 | // UPDATE AND MEANING
12 | #![no_std] and #![no_main]: These are attributes used in Rust that disable the standard library (std) and the standard main() function. This means that the code is not a Rust program typical of the user's application, but can serve as an operating system kernel or a program that runs without std support.
13 |
14 | use core::panic::PanicInfo;: Imports the PanicInfo module from the core library. This module contains information about panic that may occur while the program is running.
15 |
16 | static HELLO: &[u8] = b"Hello, World!";: Creates a HELLO constant that contains a string of bytes representing the string "Hello, World!".
17 |
18 | #[panic_handler]: This is an attribute above the panic() function that identifies it as a panic handler. This function is called in case of panic and in this case it does nothing except an infinite loop.
19 |
20 | #[no_mangle]: This is an attribute above the _start() function that tells the compiler not to rename this function during compilation. _start() is the program start function.
21 |
22 | pub extern "C" fn _start() -> ! { ... }: This is the _start() function, which is the entry point of the program. It is public (pub) and declared as extern ("extern"), which means it can be called from C. It returns the type !, which means it never ends.
23 |
24 | let vga_buffer = 0xb8000 as *mut u8;: Creates a vga_buffer pointer that points to an area of VGA memory often used to output text in text mode.
25 |
26 | for (i, &byte) in HELLO.iter().enumerate() { ... }: Iterates through the bytes in the string "Hello, World!" and performs the following operations for each character.
27 |
28 | unsafe { *vga_buffer.offset(i as isize * 2) = byte; ... }: This is the code that prints the characters "Hello, World!" to the VGA memory area. Thanks to unsafe, we can perform operations on pointers without risk, but we must be careful to avoid errors.
29 |
30 | loop {}: An infinite loop that keeps the program running after printing a string.
31 |
32 |
33 | #[cfg(test)]: Jest to atrybut, który informuje kompilator, że następny blok kodu jest przeznaczony tylko do testów.
34 |
35 | fn test_runner(_test: &[&dyn Fn()]): Jest to funkcja, która prawdopodobnie działa jako test runner, ale w kodzie podanym nie ma jej implementacji.
--------------------------------------------------------------------------------
/calc_os/qemu-system-x86_64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/autoselff/CalcOS/d80b3ec4af96aba1004c95afe1363f0ab8849482/calc_os/qemu-system-x86_64
--------------------------------------------------------------------------------
/calc_os/rust-toolchain.toml:
--------------------------------------------------------------------------------
1 | [toolchain]
2 | channel = "nightly"
--------------------------------------------------------------------------------
/calc_os/src/main.rs:
--------------------------------------------------------------------------------
1 | #![no_std]
2 | #![no_main]
3 |
4 | use core::panic::PanicInfo;
5 | mod vga_buffer;
6 |
7 | #[no_mangle]
8 | pub extern "C" fn _start() -> ! {
9 | vga_buffer::print_something();
10 | loop {}
11 | }
12 |
13 | #[panic_handler]
14 | fn panic(_info: &PanicInfo) -> ! {
15 | loop {}
16 | }
17 |
--------------------------------------------------------------------------------
/calc_os/src/vga_buffer.rs:
--------------------------------------------------------------------------------
1 | #[allow(dead_code)]
2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)]
3 | #[repr(u8)]
4 | pub enum Color {
5 | Black = 0,
6 | Blue = 1,
7 | Green = 2,
8 | Cyan = 3,
9 | Red = 4,
10 | Magenta = 5,
11 | Brown = 6,
12 | LightGray = 7,
13 | DarkGray = 8,
14 | LightBlue = 9,
15 | LightGreen = 10,
16 | LightCyan = 11,
17 | LightRed = 12,
18 | Pink = 13,
19 | Yellow = 14,
20 | White = 15,
21 | }
22 |
23 | #[derive(Debug, Clone, Copy, PartialEq, Eq)]
24 | #[repr(transparent)]
25 | struct ColorCode(u8);
26 |
27 | impl ColorCode {
28 | fn new(foreground: Color, background: Color) -> ColorCode {
29 | ColorCode((background as u8) << 4 | (foreground as u8))
30 | }
31 | }
32 |
33 | #[derive(Debug, Clone, Copy, PartialEq, Eq)]
34 | #[repr(C)]
35 | struct ScreenChar {
36 | ascii_character: u8,
37 | color_code: ColorCode,
38 | }
39 |
40 | const BUFFER_HEIGHT: usize = 13;
41 | const BUFFER_WIDTH: usize = 80;
42 |
43 | #[repr(transparent)]
44 | struct Buffer {
45 | chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
46 | }
47 |
48 | pub struct Writer {
49 | column_position: usize,
50 | color_code: ColorCode,
51 | buffer: &'static mut Buffer,
52 | }
53 |
54 | impl Writer {
55 | pub fn write_byte(&mut self, byte: u8) {
56 | match byte {
57 | b'\n' => self.new_line(),
58 | byte => {
59 | if self.column_position >= BUFFER_WIDTH {
60 | self.new_line();
61 | }
62 |
63 | let row = BUFFER_HEIGHT - 1;
64 | let col = self.column_position;
65 |
66 | let color_code = self.color_code;
67 | self.buffer.chars[row][col] = ScreenChar {
68 | ascii_character: byte,
69 | color_code,
70 | };
71 | self.column_position += 1;
72 | }
73 | }
74 | }
75 |
76 | fn new_line(&mut self) {/* TODO */}
77 | }
78 |
79 | impl Writer {
80 | pub fn write_string(&mut self, s: &str) {
81 | for byte in s.bytes() {
82 | match byte {
83 | // printable ASCII byte or newline
84 | 0x20..=0x7e | b'\n' => self.write_byte(byte),
85 | // not part of printable ASCII range
86 | _ => self.write_byte(0xfe),
87 | }
88 |
89 | }
90 | }
91 | }
92 |
93 | pub fn print_something() {
94 | let mut writer = Writer {
95 | column_position: 12,
96 | color_code: ColorCode::new(Color::White, Color::Blue),
97 | buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
98 | };
99 |
100 | writer.write_byte(b'W');
101 | writer.write_string("elcome to ");
102 | writer.write_string("CalcOS!");
103 | writer.write_string(" Made by dazai. In development...");
104 | }
--------------------------------------------------------------------------------
/calc_os/x86_64-blog_os.json:
--------------------------------------------------------------------------------
1 | {
2 | "llvm-target": "x86_64-unknown-none",
3 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
4 | "arch": "x86_64",
5 | "target-endian": "little",
6 | "target-pointer-width": "64",
7 | "target-c-int-width": "32",
8 | "os": "none",
9 | "executables": true,
10 | "panic-strategy": "abort",
11 | "disable-redzone": true,
12 | "features": "-mmx,-sse,+soft-float",
13 | "linker-flavor": "ld.lld",
14 | "linker": "rust-lld"
15 | }
--------------------------------------------------------------------------------