Rust, from First Line to Systems
Start with no Rust and finish writing the code the rest of the stack is built on.
Start free[ built, not watched ]
Real expertise matters more than ever, with AI and because of it. the research →
Kernels, filesystems, databases — built from scratch on your own machine, with an expert mentor guiding every step of the path.
Free to start · no credit card · Rust for Beginners is free
$ sboot test 07-interrupts ⋮ the build preface, and your toolchain's own output [PASS] kernel boots (1 pt) [FAIL] timer IRQ fires after sti (ticks accumulate) (2 pt) your kernel booted and ran as far as "[PASS] resumed", then stopped emitting markers. It did not reset, so it is halted or looping rather than faulting. ↳ A hang here (no output, timeout) usually means exactly one timer interrupt fired and then silence — the classic missing-EOI symptom. [PASS] no in-kernel assertion failures on the serial log (1 pt) [PASS] remaps the 8259 PIC (1 pt) [PASS] keyboard IRQ handler reads the PS/2 data port (1 pt) score: 4/6 ⋮ 2 lines — the keep-going verdict, and the stuck? sign-off$
[ meet Guru — your mentor ]
Expert review on every line you write.
[ on a pass — never on a fail ][ re-read when your diff changes ]Revise recommended — one of these would bite you.
The checks passed; the findings below are the layer the tests cannot see.
| @@ -0,0 +1,209 @@ new file | |||
| ⋮ lines 1–121 — the on-disk records, mount, and the inode table | |||
| 122 | + | /// Read from a file's data blocks into `buf`, stopping at end of file. | |
| 123 | + | fn read_bytes(&self, inode: &Inode, offset: u64, buf: &mut [u8]) | |
| 124 | + | -> Result<usize, FsError> { | |
| ⋮ lines 125–129 — the EOF clamp and the `done` / `block` locals | |||
| 130 | + | while done < want { | |
| 131 | + | let pos = offset + done as u64; | |
| 132 | + | if pos >= size { break; } | |
Guru[ craft ]simplefs.rs:132 `if pos >= size { break; }` can never fire — `want` is already capped at `size - offset` above. A dead guard makes a reader hunt for the path that needs it, and there isn't one. The clamp above is the live defence; this one is decoration. try: Delete it — or state the invariant honestly: `debug_assert!(pos < size);` | |||
| 133 | + | let index = (pos / BLOCK_SIZE as u64) as usize; | |
| 134 | + | let within = (pos % BLOCK_SIZE as u64) as usize; | |
| 135 | + | let n = core::cmp::min(BLOCK_SIZE - within, want - done); | |
| 136 | + | self.dev.read_block(inode.direct[index] as u64, &mut block)?; | |
Guru[ would bite you ]simplefs.rs:136 When `inode.direct[index]` is 0 — a hole — this reads device block 0: the superblock. It passes because nothing in this image is sparse yet. The first write past a file's end changes that: reads in the gap hand back superblock bytes as file contents — a real bug hiding behind a green check. try: A hole reads as zeroes: `if ptr == 0 { buf[done..done + n].fill(0) }` — only a nonzero slot touches the device. | |||
| ⋮ lines 137–209 — the copy into `buf`, the loop close, and write_bytes | |||
[ when you’re stuck ]
Ask about the check that is failing and you get the one question that moves you — never the answer pasted in. Underneath it, on every ask, a written hint Guru does not need to be online for.
pub fn write_byte(b: u8) {
out8(COM1, b);
}what am I missing?out8(COM1, b) hands a byte over whether or not the UART has room for one, and your init switched on a queue in front of the wire. So: where does the UART tell you it has room again? Your own run answers half of it — count how many of the 64 arrived before the tail stopped.$ sboot hint 01-first-lighthint — 01-first-light · fb.background # your failing check [hint 1 of 2 · fb.background] Nothing reached the screen at the point we sampled. The mostcommon cause is that your fill loop never actually ran — thescaffold calls gfx::main once and halts, so if fill() isn'tcalled from main, the framebuffer stays whatever the bootloaderleft. Confirm main calls fill before anything else. run it again for the next rung (2 of 2 — the debug ladder).$
[ the paths ]
Start a path and you finish with a system you built — every prerequisite already on it, in an order already worked out.
Start with no Rust and finish writing the code the rest of the stack is built on.
Start freeBoot your own kernel, then teach it memory, scheduling, a filesystem, and a shell that answers you.
Start freeThe same machine, in the language it was written in — boot your own kernel in C and own every byte you hand the hardware.
Start freeBuild the engine under the query — pages, B-trees, and a log that survives the crash you cause on purpose.
Get notified1 of 6
[ inside one lab ]
Every lab: concept, canon, build — with Guru beside you, and a grade that comes from running it.
One page on the idea you are about to build. Short on purpose: it gets you to the keyboard.
The actual chapter, paper or datasheet, in the original, with the part you need named.
You write it into a real system, and it is graded by running it.
Instant feedback on the published checks — and it never quotes our tests, only your own kernel.
$ sboot test 07-interrupts── build: `cargo xtask build` — your toolchain's own output follows [PASS] kernel boots (1 pt) [FAIL] timer IRQ fires after sti (ticks accumulate) (2 pt) your kernel booted and ran as far as "[PASS] resumed", then stopped emitting markers. It did not reset, so it is halted or looping rather than faulting. ↳ A hang here (no output, timeout) usually means exactly one timer interrupt fired and then silence — the classic missing-EOI symptom. [PASS] no in-kernel assertion failures on the serial log (1 pt) [PASS] remaps the 8259 PIC (1 pt) [PASS] keyboard IRQ handler reads the PS/2 data port (1 pt) score: 4/6 ❌ keep going — see the failing checks above.stuck? sboot hint · sourceboot.com/courses/os-rust/stages/07-interrupts#stuck$
The official run. Your machine builds it and boots it once; we judge that run and record it — a grade earned by code that actually ran.
$ sboot submit 07-interrupts── checking 07-interrupts locally first (one build, one run)── build: `cargo xtask build` — your toolchain's own output follows ── local check passed (6/6)── packaging os/ (source only)── submitted (238 KB) — graded on the server [PASS] kernel boots (1 pt) [PASS] timer IRQ fires after sti (ticks accumulate) (2 pt) [PASS] no in-kernel assertion failures on the serial log (1 pt) [PASS] remaps the 8259 PIC (1 pt) [PASS] keyboard IRQ handler reads the PS/2 data port (1 pt) score: 6/6 ✅ official grade: 6/6 — recorded Submitted → sourceboot.com/courses/os-rust/stages/07-interrupts?submission=…#review read your review, then press Complete there — that's what finishes the lab$
[ your path is open ]
Build something that actually runs before you decide anything.
Every completion is a system that actually ran — an official run of your own code, on your path for good.
Prerequisites live on the path itself, so everything you need arrives in the place you need it.
What you build is a git repo on your own machine from the first commit — yours to keep, with none of our grading inside it.
Get the updates instead:
New paths, new labs, and the ones that just went live. No noise.