2019-11-09 23:35:13

Hello all,
So I thought I might actually post about this now since I linked to it in another thread on this forum. I've held off on this for some time because I don't think its remotely close to being truly qualified as an OS. But its something and I'm here to share that. smile
Please note that I am in no way trying to compete with Linux, Mac OS, Windows, BSD, QNX, OS/2, etc. big_smile I am just doing this for fun and because I love learning about these things. I am hoping to share that knowledge with others.
Also note that the documentation is very sparse (if not downright nonexistent). At this time documentation is not my highest priority, especially given the fact that I have college and real life getting in my way, so I do apologize for that.
Note that this OS is written in Rust and, though I'd be happy to teach people on how it all works, playing with the code is a hole different matter. The key warning is to not run this on real hardware. This OS is not ready for that. Feel free to help me out with the project if you so like (but I do expect you to know what your doing) but never run this on real harware. A VM can be broken all you like and can be easily replaced; a real computer, not so much.
This OS does not support even 1/32 of what Linux does when it boots up. It is very minimal, does not support SMP, cannot execute programs, and so on. I'm working on that but right now I'm stuck on getting disk IO working.
The project is located at https://github.com/ethindp/kernel. Feel free to contribute, though please, please debug your code before you submit it upstream -- at least make sure it doesn't throw a processor exception (#GP, #PF, ...). Also, if anyone does want to dive into this, I commend you and would like to hereby call out anyone who chooses to aid me in this endeavor insane. Of course, I started it, so I'm a bit insane too. (And how would life not be fun with a bit of insanity?) Either way, be ready to digest truckloads of information because you are *not* writing a computer program any more. You are not writing a game engine or even a game. You are writing drivers and hardware abstractions to build the foundation where a game engine and game can be built on. I will be happy to provide you resources to help you out, though I don't use the primary language for OS development (C) so you'll need to be reasonably good at porting code, or be able to make up new ways of doing things.
This OS currently supports... not much. It is able to catch all the main interrupts, use the real time clock, initialize the Intel High Definition Audio (HDA) controller, enumerate PCI devices, read input from the keyboard, play beeps through the PC speaker and that's pretty much it. There are some files in the repository that are not linked into the main build -- this is usually because they are still being worked on and it would make the build fail or be even more unstable should I link them in. Again, do not be afraid to dive in to the code, and do not be afraid to ask questions and contribute.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-10 10:57:26

Oh man, that's awesome! It's bad I am that stupid lol

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com

2019-11-10 12:15:18

wooooowwwww dude! that's completely! completely ausumn thingy! wish you good luck!

Yours kindly

2019-11-10 21:16:34

@2-3, thanks for the words of encouragement! I hope I can get disk IO working but its a pain!

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-10 21:38:49

Oh I knowit is. I have read the tutorial that you derrived from and I understand a lot of it. It's not that hard! Good luck with the Disk IO! BTW you never know where your work leads you

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com

2019-11-12 21:22:04

Hi,
Here's what I think is going to happen, and I mean this in the best possible way, no hard feelings. In fact, completely the opposite. I'm excited about this project.
Once again, to repeat: I'm excited about this project.
I do have a feeling that this is going to take quite some time to get off the ground. I would not be surprised if it will take, even, years, and people need to know that. Heck, I would not be surprised if Ethin already knows this. This will take patience and this is probably going to be a challenge to complete, but I am interested to see where this goes.

2019-11-12 22:07:13

@6, trust me, I know. @the rest of you, Don't expect anything super-ultra-awesome any time soon -- an OS is nothing easy to create, I assure you. And don't even think about cloning one, either -- that's just... incredibly hard, even impossible if you don't know what your doing. I do encourage people to help though -- I don't have much experience in this area either, and am learning via other code examples and online guides.
Disk IO is especially being a pain; I get the feeling I'm going to have to over-use the Volatile crate all over the place, which will make my code downright disgusting to read. (Then again, code for an OS can't exactly be super-pleasant to read anyway...)

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-13 11:59:59

hi,
I wish the best of luck to you.
now my words for such projects:
a while ago, I wrote an os in C, and I left that off. (just I wanted to learn).
now for disk IO, you need to learn more about lba, chs, different filesystems like fat32, ntfs etc.
also, debugging is a pain in the ass when you don't have a screen reader onn it, and in the boot time (because of these I gave up debugging it).
also, consider things like DMA, spin locks, IPC, etc.
and guys if you want to learn more about OS development, minix is a good thing (people who have never coded by themselves and tried to clone each and every game just ignore this,, you can't compile, and then clone it).
also, for executable stuff, I recommend you to use the ELF format (the specs are available everywhere and so much code examples are available for it).
things like a c-library implementation (stdio and so on) should be implemented as well.
at last, I didn't get your code (since I don't know so much about coding with rust)

2019-11-13 17:40:06

@8:
1) I'm only trying to read sectors from the AHCI disk at the moment; I don't care about FSes right now.
2) Debugging is much easier when you've got QEMU with its GDB stub (though its still a pain sometimes).
3) DMA/Spinlocks/IPC will come much, much later. I don't even have SMP yet! smile (Though my kernel does use spinlocks because rust demands it of me.)
4) Yep, going with ELF was my original idea anyway.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-13 18:37:19 (edited by visualstudio 2019-11-13 18:39:54)

since I don't work with rust, I can't say that much about it.
but, you should implement spinlocks at first if rust requires it.
as for the debugging,, I was using bochs to debug my os and didn't try qemu, though it may seem great given that it supports the emulation of many processors such as arm.

2019-11-14 00:39:56

@10, yes, I have a crate called spin which implements spinlocks for me (though I'll probably give 'em a shot sometime since I've never implemented them before). I'm not really sure how to get Disk IO working. If I read the HBA port into a struct, I get the appropriate SATA signature (0x0000010). If I read it directly with MMIO calls that I've written in my kernel, I get 0x11300000101. I'm thinking about making the entire thing use the Volatile crate and then using volatile reads and writes to fix the current problem I'm having, but that will get really, really messy.
My current problem is this: I rebase the port to 0x400000. I then try to ask the controller to read the first sector of the disk (I'm just looking for a boot signature, 0x55 0xAA). However, I always get nothing back. Kinda confused.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-14 05:57:05

the thing about disk io is you need to read them in inodes and then allocate memory for your files
then when a process calls for example read() with a file* object, you will return the allocated bytes to them.
the thing is, you need a kind of structure for each of the file-systems that you want to implement.
checkout here

2019-11-14 05:59:56

@12, trust me, I've used that wiki quite a bit -- that's how I got PCI enumeration working. Befoe I can even read FSes though I need to be able to read disk sectors, which I'm working on right now.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-14 15:13:42

Sorry if this doesn’t help, but I found this Hopefully it can help you
https://rust-embedded.github.io/book/intro

2019-11-14 20:40:42

@13 you are right.
the thing is, for sata devices you need to implement pci first.
it's specifications are available online, and even you can find it on osdev wiki.

2019-11-14 20:50:36

@15, and I have done that. My PCI code is available at https://github.com/ethindp/kernel/blob/ … src/pci.rs.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-15 10:25:03

That code is perfectly readable, I must say @Ethin. I understand 80, 90% of it. I am not sure about U32, though.

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com

2019-11-15 10:45:47

@17, u32 is unsigned 32-bit int, u16 is unsigned 16-bit int, and so on. Same for i8/16/32/64/128. f32 is a single-precision floating point number while f64 is a double-precision floating point number.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-11-15 13:11:48

Where did you get the specs from? How you know that some hex numbers are functions, and so on?

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com

2019-11-15 18:26:08

@19 these are chip numbers which help you interact with the hardware.

2019-11-15 19:21:32

@19, if you mean class codes, subclass codes and program interfaces, all of this is not only available in the PCI database but is specified in technical datasheets and specifications. It has to be; if it wasn't, an OS would not be able to know what's what.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2020-01-11 21:36:32 (edited by Ethin 2020-01-11 21:44:41)

I'm back with some major updates to the OS thus far, with, perhaps, some small performance increases here and there.

General
  • The disk I'm using has been recreated. Using NBD (network block device) technology of the Linux kernel, I was able to mount this QCOW2 disk on /dev/nbd0 and format it as GPT with EXT2. Since EXT2 is ridiculously slow at formatting the disk, the disks size is quite small (though that is also because of git hubs file size limitations). It will be enough for our purposes for now however.

  • I've increased the overall memory requirement of the emulation to 1 GB of RAM. Though I could go much (much) higher, my kernel has yet to require that much RAM yet. Hell, it could operate under 16 MB of RAM just fine.

Code quality
  • Last week I ran clippy on the entire project and have gone through and fixed about 99 percent of its warnings. I have also turned on nearly every lint that the Rust compiler has and set it to 'deny', pretty much forcing myself and contributors to use higher code quality in general. This way, its really obvious when someone contributes something and they use #[allow()] to get around a lint. Originally I wanted to set this to 'forbid', which prevents people from overriding the lints, but the macros my kernel uses (i.e. lazy_static!) caused compilation errors, so I'm stuck with deny for now.

Core: interrupts
  • The RTC timer now uses a reader-writer lock instead of a full mutex lock. For those wh odo't know, a reader-writer lock allows unlimited readers to read the data that the lock is protecting, but to write to it exclusive acquisition is needed. A full mutex lock, on the other hand, requires a caller to gain exclusive access to the lock to read or write to it, which I believe was making my code a lot slower than it could be. To compensate for the reader-writer issues, I have modified the get_tick_count() function and the RTC timer interrupt to attempt to acquire the lock. If the RTC timer interrupt is unable to acquire the lock, it never increments the value held within. Since this interrupt is called every 122 US, there's currently over a 70 percent chance it will acquire it within a few ticks, if even less. The get_tick_count() function returns 0 if it can't acquire a reader lock when it is called. This will not affect sleeping, since the value will appear to never have changed.

Core: PCI
  • The PCI subsystem now uses a linked list instead of a Vec. While both of these allocate memory, the LinkedList structure only allocates memory when an item is added to the list and not when it is created, saving a (potentially) costly memory allocation until it is actually needed. This also creates a performance boost in the PCI enumeration code since adding elements to the list should always occur in O(1) time unless there are other outstanding circumstances.

  • The PCI interface device scanning functions for drivers has been changed. New contributors, when writing drivers, should use pci::find_device() or pci::find_device_x() to locate a device instead of iterating through all devices. The function for retrieving a list of all devices has also been removed, though it may be re-added later. The pci::find_device() function takes a class, subclass, and program interface, and returns an Option<PCIDevice>, and pci::find_device_x() takes a class, subclass, an array of vendor codes, and an array of device IDs and returns an Option<PCIDevice>. Both functions are always inlined.

Core: memory manager
  • Error checking has been added to those functions that did not have them but that called unwrap() anyway.

  • The kernel is now assigned an 8 MB heap, though this is probably overkill and the performance cost is definitely noticeable.

Driver updates
Keyboard driver
  • The keyboard driver now uses 4 statically allocated buffers instead of dynamically allocating memory for every key event. Each buffer contains 512 Option<> items. If the buffer is full, new keys that are received are dropped on the floor. This will make actual UIs difficult to write since the keyboard driver does not (yet) follow the Reader-Writer lock paradigm like the RTC timer does, though I will be updating that sometime soon. However, the remaining changes will make the driver much easier to use when called upon.

  • The driver has been pretty much entirely rewritten to use functional elements instead of handwritten, untested code. During the rewrite I did my est to take advantage of all of Rusts functional capabilities instead of trying to handcraft my own. As an example, instead of a match statement on practically every other line,causing overall messiness, the driver uses functions like zip(), iter_mut() and so on.

  • The keyboard driver now exposes two "truly public" functions, read_key() and read_character(). This will make writing UIs a lot simpler since you do not receive a tuple of values like you did before and instead can filter based on the state of the system at the time you'd like input from the user. Both functions return an Option<>: read_character() returns an Option<char> and read_key() returns an Option<pc_keyboard::KeyCode>.

Intel HDA
  • The HDA driver now stores, statically, memory addresses for the Command Output Ring Buffer (CORB) and Response Input Ring Buffer (RIRB), which it also dynamically configures and sets to random memory addresses. It is now fully capable of transmitting commands to the controller and receiving responses from it. Currently it still beaks (though I am attempting to determine, with the OSDev community's help, whether it is just Qemu being faulty or whether my code is actually broken.

AHCI
  • The AHCI driver has been unlinked from the execution chain for now since it is broken. It is still built but it is never initialized.

ATA
  • An ATA driver has been added. ATA is the precursor to AHCI, only allowing 4 disks instead of up to 32, but both are very interconnected and closely related. The ATA driver uses port IO instead of DMA, which causes a slight performance degradation; however, this performance cost is payable for now and allows us to move onto greater and better things. This ATA driver is able to send commands to the ATA controller and receive responses from it, and is also able to read sectors from the disk. This has, for example, allowed me to determine the number of sectors that the disk has, as well as find the GPT partition table header signature. The module is divided into five separate submodules, most of which are unused/still in development as of commit E6AED9F:

    • The main module contains ATA commands as defined in INCITS 452-2009 (R 2019). All of these commands are marked as 'unsafe' since port IO is used and sending values incorrectly to the controller could cause undefined behavior. Commands that have "safe" equivalents (i.e. commands that build data structures for easier handling and such) have the suffix '_raw' added to them, indicating that, when called, they will return raw data instead of doing anything useful with it. The caller will then need to interpret the returned data themselves.

    • The 'identification' submodule contains data structures for the Identify Device command. Identify Device returns 256 words (16-bit values) that contain device characteristics, capabilities, etc. See 7.16 of ATA8 ACS, INCITS 452-2009 (R 2019) for more information on what each word contains. Though they are incomplete, the data structures in the identification module itself may be of use in understanding the Identify Device command as well.

    • The "security", "smart", and "dco" submodules are currently excluded from the build; when complete, they will include functions for accessing and manipulating the security feature set, the SMART feature set, and the device configuration overlay (DCO).

GPT
  • A GPT driver has been started to begin the process of parsing the data at LBA 1 on the disk. LBA 1 contains the GPT partition table header, and LBAs 2-33 contain partition table entries. Once the GPT driver is complete, the ATA driver will most likely also be complete, makign it possible to read and write data on the disk (this also includes compact flash media if supported using the media card passthrough feature set). This will also begin building the chain of modules required to read and write data within filesystems so that we can complete the virtual filesystem layer. Once the VFS has complete and we are able to read at least one filesystem, even minimally, we can begin on making it possible to load kernel modules from the filesystem to allow the kernel to be extended.

Other changes
  • The kernel now requires the RDRAND instruction to be available on your processor. This requires you to run qemu with the -cpu host or -cpu max argument. Failure to do this will cause the kernel to refuse to boot (it will throw an error demanding RDRAND).

That's all the changes I've done thus far. Audio still doesn't work (unless you like the PC speaker that is) though I think I'm getting somewhere! If anyone is willing to take the plunge into low-level code, I strongly encourage anyone who would like to help to dive in and go! smile If you'd like to contribute, the best way of contacting me would either be via email/PM, or by contacting me on TT. I'm not on Skype as much any more, though that is another way of contacting me.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2020-01-11 22:11:46

Congrats man. I really appreciate and admire people like you. Linux also started as a hobby OS lol. I will look on to the code as I am fascinated how such a low level thing works... Congrats and I wish you the best!

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com

2020-01-11 23:20:40

@23, if you really want to understand all of the gory details -- what all the bits mean and all that, the structure names and stuff won't be enough (for things like the HDA driver or the ATA driver). For the HDA driver, you'll need the Intel HDA specification, and for the ATA driver you'll need at least two standards, both of which are unfortunately paid. The first is INCITS 452-2009 (R 2019), ATA/ATAPI Command Set (ATA8-ACS), which is $60.00, and the Serial ATA specification Revision 3.4, which is $75.00. Its unfortunate that they're paid, but they are, and the only way for all of this to even be remotely workable you've gotta have them. The OSDev wiki is also an excellent resource, but it cannot possibly make up for what the standards cover (its ATA command matrix isn't even accurate and holds commands that are no longer defined in the latest revision).

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2020-01-12 01:34:23

I know that Ethin... Thank you though smile`

If you want to contact me, do not use the forum PM. I respond once a year or two, when I need to write a PM myself. I apologize for the inconvenience.
Telegram: Nuno69a
E-Mail: nuno69a (at) gmail (dot) com