Lab 1: Booting a PC
pdos.csail.mit.edu
pdos.csail.mit.edu
Some folks excelled (though they put in 15+ hours per week on average, which is quite high), some cratered and I needed a backup plan for them to make progress.
I know this because for the final project my partner and I ported the OS to 64bit. Although the number of changes was not too large, we spent hours debugging low level x86_64 stuff. Although we learned a lot, I think it is a good idea the labs provide the boilerplate.
When I was in college, lab assignments were typically printed or photocopied sheafs of paper, and handed out. To submit one's lab work one printed out the results, and handed them in, or called the instructor over to watch one's demo, etc. I would have loved to have been able to use existing tools I already knew how to use to manage all that automatically.
Even better for students that don't have a lot of coding experience. Rather than slogging through some terrible Blackboard-esque environment that they'll never see again to submit assignments, they're actually becoming comfortable using versioning and development tools that are the current industry standard. Very useful for everyone.
Things like "Using an API Key", and "Using git" cause students to HAVE to go above and beyond the assignment Because they will undoubtedly run into a problem with some of these extra steps along the way.
I think this type of learning can be more beneficial than the assignment itself. It's real problem solving using the computers.
That's just cool to see.
If a course with this level of detail had been available to me, I would have taken it in a heart beat. Mmm...boot loaders.
On the flip side, I can also understand why you wouldn't want to start an Operating-system engineering course with UEFI.
Unlike BIOS (a set of historically accumulated hacks, which works in a given way because they just do), UEFI is quite a big thing, a big spec and a OS onto itself. It would probably involve quite a bit of indirection.
On the flip side (again), experimenting with the boot process on (real) UEFI machines would probably be much simpler than trying to program boot PROMs and similar stuff they resort to when experimenting with QEMU.
It is rather easy to build a multiboot-capable ELF file that can be easily booted on real iron as well as emulators.
This will directly set up your computer in protected (32 bit) mode (NOTE: working in 64 bit "long" mode is a bit more difficult, for educational projects, it's best to stick with 32 bit mode). The protocol also has specs to set up a video mode and provide you with a pointer to the framebuffer (otherwise you'd need to fall back to 16 bit real mode, and use BIOS interrupts for setting up a video mode) and provide some information about the machine in a structure provided to the kernel on boot.
Booting directly with UEFI might be more and more viable option as time goes by, but I think that multiboot is still more viable (things might have changed, I haven't done OS development in a few years).
[0] https://www.gnu.org/software/grub/manual/multiboot/multiboot...
Oh, you meant the ARM? Oh, my, no, the Pi doesn't boot from that. The ROM loader starts the SDCard and loads BOOTCODE.BIN to the VC4 with cache-in-RAM mode; that's its equivalent of the bootblock. The ARMv6 isn't even turned on until the next chain later (used to be two, from memory?).
So, you know, if you fancy a much more fun, more advanced, challenge, it's right there waiting for you, under the crust. Have fun. Let me know if you find a diagonal vector addressing mode or a good way of shuffling words! <grin>
(PS: There is actually someone at Broadcom working on open-source firmware for the Raspberry Pi, or was last I checked. They're going to have to rewrite it: the ThreadX RTOS they used is commercial. But he has firmware documentation, at least. You have… some of it.)
In other words: it would not be fun to do this using a RasPi (depending on your definition of "fun" of course). You would be spending lots of time with scarce documentation, dealing with practically no debugging aids and the only way to know if your code is working is whether a LED lights up and no way to debug failures. If you had a development board, perhaps you'd have JTAG or other debugging means available but I'm not sure if you can find this on a RasPi. You'd end up with very little transferable knowledge from this project.
Of course, working with scarce documentation in a harsh early boot environment is a valuable skill in itself, but not the kind of stuff I'd voluntarily get into. This stuff is hard enough to do on a well documented, widely available platform like the x86 PC.
However, if that plugs into the "big" ARM core, that's of no use with the early boot process (which uses the VideoCore, according to the post below).
Interesting notes about this class:
1. This is the second of two one-semester systems programming classes. In the first semester, you learn how to implement ext2. The bootloader assignment is mostly a minimal refresher of the same subject, so you're expected to have remembered from last semester how to traverse the filesystem.
2. You have to write the whole boot loader yourself, aside from some assembly code you've been provided. It runs in 16-bit mode, so you can't use gcc, at least not easily. You use bcc; Bruce's C compiler, which doesn't really read ANSI C.
2a. This actually continues throughout the entire class, during which you will eventually build an entire kernel, in 16 bit x86, using Bruce's C compiler. I don't know who Bruce is, but the professor apparently thought that 32-bit mode did too much of the work for you and wanted us to understand how to do some of the stuff (i.e. switching between kernel and user mode, I think?) ourselves.
2b. Bruce's C compiler lacks a lot of interesting features of more modern C compilers, like function signatures. In Bruce's C compiler, much as in early dialects of C, you can call any function you want and pass whatever arguments you want; the only thing the function does is read it off the stack. Downsides: whatever paltry type safety you get from C is gone; you can pass a long to a function that expects a short and it'll just grab enough bits off the stack to make a short. Upsides: variadic functions, like printf, are marginally simpler to implement; when they released some of the very earliest C/Unix code, I found that my printf had a very close resemblance to the original.
3. You have to fit the whole bootloader in 1 KB, which is not the kind of programming challenge I had yet faced.
4. Since the entire class is taught using ancient technology, there's obviously no emphasis on things like git or API keys. I personally took this class as an opportunity to teach myself git in order to maintain my own sanity.
The professor who teaches these classes is a bit of a legend among CS alumni at my school, partially for these lab assignments and partially for his lectures, which involve extended metaphors, and in which he doesn't erase anything he writes on the whiteboard, instead diagramming or writing over whatever he diagrammed or wrote before.
If you were doing it in Asm, 1KB is a lot of code. The regular DOS bootsector is 512 bytes, of which only ~400 are available for actual code. It doesn't take all that much code to read in a few sectors from disk into memory and jump to it, which is all that a bootloader does.
The stuff that just happens to get stuff working is amazing.
Which is a great reason not to ever use GNU assembler for anything.
> we will be using the GNU assembler.
AAAAAAGGGGGHHHHHHHHH
https://github.com/0xAX/asm/pull/2/files
I used to think it was "nasm or nothing" - but gas+intel seems rather pleasant too.