uh yo yo yo what's up what's up welcome
back today we're working on my operating
system it's called stream OS for now um
puns are welcome pun suggestions welcome
I should say um and this is just like a
x86 operating system it's written for
fun there's no real goal um we're just
kind of like trying to poke and prod see
how operating systems work and maybe use
that as a way to learn about computers
programming a way like maybe build an
intuition about how real operating
systems work etc etc um but really you
know if we're going to be honest like
it's just cuz it's fun um yeah
so where we're at right now is we have
an operating system that uh it boots it
has like vectors Maps has memory
location has like some form of
concurrency it has uh serial logging
unit testing uh where logging it goes to
like standard output when I run through
a virtual machine um has like a pretty
shitty clock um and like a ethernet
stack so that we can you know render a
web or serve a web page um do like TCP
stuff UDP Stuff Etc uh we have like some
like shitty form of Graphics where we
can like draw pixels to a frame buffer
and we have keyboard input
handling um so that we can like control
things in our Games
Etc uh what we're working on right now
is uh multicore support
so as of right now our whole operating
system kind of works under the
assumption that we are running on one
core and as
we uh we we're working towards enabling
the other cores fixing all of the
assumptions about one core and uh trying
to run our like task executor in like a
multi-threaded way so that it pulls
tasks from whichever cor is free to do
work and we'll run it
there um yeah so where we are working in
right now is okay let's see so metric
multiprocessing
have so in order to boot uh boot a
symmetric multiprocessing system which I
think is just the fancy word for um all
cores do similar amounts of work they're
all similar strength they have like same
memory space maybe that's not part of
the symmetric m multiprocessing
definition but that's like my
understanding of at least my setup
um and in order to do this they need a
handle to this thing called like the
aipc uh which is the uh Advanced
interrupt
controller um and in order to get a
handle to this we need to parse um
some this thing called the madt multiple
apic description table RI is just going
to be one per
core um these come from
let's see acpi
tables right and these tables come from
this thing called the root system
description
pointer and this thing comes from
multibot 2 which is like this um boot
standard that like grub implements so
like if you like ever booted Linux you
go you boot and you get this like little
menu of like oh you can boot a moon
right now um that will that's grub and
Grub does a bunch of like the like prein
ization stuff so when my CPU boots it's
in like 16bit mode because like 30 years
ago people ran Doss in 16bit mode or
something and like when they released
32-bit processors they didn't want to
like up the 16-bit stuff so they
were like okay we'll like start in 16
bit mode and you upgrade so the
bootloader handles that upgrade for us
it also handles a bunch of like
interaction with the BIOS because a
bunch of the BIOS stuff can only happen
in 16 bit mode if I understand
correctly um so what we do is we like
ask the bootloader to do all of this
like initialization and like finding
asking the BIOS like what's plugged in
and like what features do I have and how
many CPUs do I have all of that comes
from bios calls or ufi calls on neuros
systems and uh we basically are saying
like hey grub you do that for us and
we'll implement this like multi Boot 2
spec and you just give us that
info um and so that's what we're working
on right now is implementing multi-b 2
support uh we originally on our first
boot we implemented multi boot One
support because it was easier and I
think probably like the when you're just
go like how do I boot an OS oh was de
please tell me I think that that's where
it started us um and so now yeah we're
getting we're going through Multi 2
stuff so last stream we got pretty far
um we got to the point where everything
was working the same on after boot
except for our frame buffer was not
getting
initialized um I'm sorry we actually
initialized the frame buffer but we had
a trouble getting we didn't ever get the
handle to the frame buffer from within
our
OS um so that's what we're working on
now uh let's just quickly checkpoint
here and let's see if we can like
quickly get into a state where we can
show the current
features um so I think if I actually I
think if I cargo run right
now uh without
GDB uh oops it's actually already
running um this boots it ini izes a 640x
480 window um it does some like demo
stuff where it says like hey look we
have a vector we have a map we have like
date time and we modify the date time in
the RTC and we can get our Mac address
from the ethernet card and we can like
find the MAC address of another PC on
the same network and we can
sleep um and if I set up netcat I can
like say hello and my OS receives the
word hello and it sends it back um so
like everything's kind of working uh but
we used to have a game in this window
and that's not working right
now uh yeah so where we got to at the
end of last stream was we thought that
uh we were like debugging why we weren't
getting the frame foro so the the idea
behind multibot
2 is uh they give
you uh a header that has like uh sorry
how do I say this on operating system
boot they put a pointer in one of your
like registers on the CPU um and if you
look at the pointer there you get like a
pointer to the structure maybe we start
drawing it right so in your like
CPU CPU you have like this
register uh
ebx and he's like a pointer to some
memory okay and in here we have like
this multi booot
structure
um which
has this is probably not it this is the
requester side uh here we go which has
like a
size
and then he just have like then he has
like a like list of tags so we have each
tag will have like
ID um
size and
data and this block is going to happen
like end times so this is going to be
copy
pasted like here here here right until
we run a
room and each one of these tags has like
different stuff in it
so um what we're trying to get to is
we're trying to parse this like frame
buffer info one and and our current
state is that we never find a tag with
type
eight and last
stream uh we were kind of like printing
out what we got here so here we're
saying like oh we have uh tag 21 tag one
tag two tag 10 uh tag
six and then we get into the state where
after we do tag six we have this like
tag 5539 and that looks like very
clearly wrong right there we don't have
five 1,539 different types of things
that we could do and we have one that's
like type zero size 27 I think type zero
doesn't even exist if we look type
equals
z we don't see that at
all
uh yeah so we we were getting a point
where like we're clearly um making a
mistake in our parsing here and so
that's what I wanted to look at today is
trying to like fix this get a handle to
the frame buffer fix the frame frame for
Stu we have feature parody with when we
were booting with multi boot one and if
we get there in a reasonable time then
probably the thing to do is start trying
to like work towards getting a handle to
the acpi
tables uh
yeah that's that's it so let's kind of
just get
moving
okay so here clearly uh so how do I say
this we kind of validated that the
memory map that we're getting um in from
multibot is working this is like uh a
list of memory regions one of which is
like our entire memory space and last
stream we validated that um if we
increase the total size of memory that
qyu our virtual machine provides our
operating system we do see that number
in the memory map kind of like match up
with what we're
providing um but the thing after that is
just like totally um and so it's
possible that when we're parsing
uh this like uh size field for each of
the tags we were kind of going like read
the size jump to the next one read the
size jump to the next one read the size
jump to the next one depending on what
the size value is and it's possible that
it's wrong um that memory is corrupt or
that we are parsing incorrectly and this
parsing incorrectly is like the most
likely thing because we don't know what
the we're doing we've just kind of
like open this Doc and started typing
without even really reading it all the
way um so I think that's where we want
to look here so the way this works is in
our multibot 2 stuff this is our
iterator yeah all we do is we have like
a location that we start at an end
location and we check if we hit the end
um yeah so and then we check if there's
like maybe there's a null Terminator tag
as well which also we exit
on um so when I was just scrolling this
multipot 2 thing like literally just now
um I did notice that they have some
sample code here so I do want to see um
what they do
here
so here they
have total size comes from the multibot
header and then they iterate over tag so
they say tag is equal to Adder Plus 8
while tag type is not equal to multi tag
and
we tag is equal
to
the current tag plus the
size plus 7 and inverted by
seven so This Is How They 8 by align
their thing
um and I am now realizing that my
version of 8 by alignment is just
wrong oh okay so
what I did here was I tried to say um
size mod 8 is going to be like some
number between 0o and seven right I
tried to say like well if the if size
mod 8 is equal to one then I should do I
should like add seven to
the uh thing to make sure that we're
aligned to addresses 8 um so I did 8
minus seze one 8 that's great except um
in the case where size is zero we're
going to increment by eight uh for no
reason and so what these guys
did is just a the more correct
thing and uh they're saying that
size what
equals
uh we say size equals size + 7
and Boolean KN of
seven
um and what this is going to do is we're
going to say uh if size is zero we're
going to get uh
size sorry if size is how do I how do I
draw
this say we have
like okay what this is this is a mask
of uh seven is what zerx F no
um okay Cal does this show me in bits no
it doesn't Okay uh we'll boat up python
then Python 3 um so we'll say format
this is Boolean and we'll print
7 so this 7 is
111 right so we're saying that these are
the bits that we want set or that we
want to clear right anything from 0 to 7
is is invalid because we want our
pointers to be eight bit B bit
aligned so what we do by saying this not
seven
is uh we convert this
to what the
hell is it not seven no I well basically
we convert like 0 B 111 to 0 B
1111111111 followed by three zeros at
the end right number of ones here isn't
relevant it's just that like all of the
like we're masking out the top
section of our of our value and here we
add seven so that we are always in like
the worst
case
um yeah and I think that that kind of
works
out so let's see if that fixes
anything hey there we go so these types
are now reasonable okay and now we are
in fact getting our frame buffer info
which is
great and we are moving and grooving
very nice
so here we'll say that we fixed size uh
tag size alignment
bug
okay and so now we're going to parse
frame buffer
info and it would be nice if we could
see all this we're gonna make this like
guy stuck in the Maze a little smaller a
little stretcher a little more
stretched and uh here we go okay so
what's next next is now we're actually
getting frame buffer info and so here we
can fix
this we'll Panic here we'll say failed
to get frame buffer
info in reality maybe we should just
return on
here right in because so that our
operating system still runs without a
frame buffer and here here we'll say uh
we return an option frame buffer
info and now we actually have to uh
parse this guy
so what would be kind of fun here is if
we just print them out so say print
line I so let's see what we get here and
we'll say uh frame buffer info is
this
uh here we need to fix this
guy
um none of this matters this does so
this is frame
buffer all
right cool so now we do in fact get a
frame buffer info and he's got a type A
he's got an address he's got a pitch
he's got a width he's got a height bits
for Pixel frame buffer
type
uh R red green blue
stuff and I am noticing that I think
that this is equally incorrect as it
was in our multi one
implementation so back when we set up
this like frame buffer stuff we did
notice that the
uh positions don't match in real life
what we actually see so we ended up
swapping red green and blue and it looks
like if I remember correctly I think
that we have to do that same hack again
uh so what I'm going to do is I'm
actually just going to copy paste all
this out of the frameo for one
stuff
uh
and uh put it in the multibot 2 stuff
and kind of see if it lines
up okay so here we're going to say turn
some
this and this is no longer self so what
do we have here uh in multi boot
one we converted the color size from
bits per
pixel uh oh our size looked wrong so
that's the first thing we have written
down here is that the sizes didn't all
line up and this is true again right so
red is zero but the red size is 16 that
doesn't make sense because we have 8
bits per
pixel oh
no hold
on no this still doesn't make sense
right so I was going to say that this
would kind of line up the 16 kind of
makes sense if they have a 32-bit thing
but it's like
24-bit um if it's supposed to be 24 bits
but we have 32 bits of data so that it's
like aligned on a pointer AIS we might
have like red takes
[Music]
16 uh like this green takes eight blue
takes
eight so we would have like
r g
B uh but these offsets don't align with
that right so like the fact that the
green field position is
eight and the blue field position is
eight it's like what the are they
talking about and the blue Mas has zero
so let's actually read this back again
and see if this actually makes sense in
the multi 2
world let's check that so here in the
multip two
speec um let's look at the frame buffer
stuff
so frame buffer BPP is equal
16 frame over pitch is expressing B per
line yeah okay let's see if we can find
somebody who's using this red mask
size
nope yeah there's something wrong here
uh so we're just going to we're going to
ignore
these values again for now uh because
this doesn't line up right because this
says here that we
have red field position
zero so if this
is
zero um with a mask of
16 but then the green position is eight
so that would be
here and then we also have a blue field
position of
eight which doesn't make
sense I wonder if we're actually have
these inverted in some
way right this would make a lot more
sense if the blue field position was
Zero the green field position was
eight and the red field position was
16 so if we were like off by one bite
this would be
168 88
Zer something oo so that could be it if
we're off by one that would make
sense
um so let's see if that if we
can kind of try to prove that to
ourselves because that' be nice not to
have to do this like
heck um so what I'm going to do is I'm
going to go into
GDB and I'm going to set a break point
at this
line
and uh I guess
I'll just sit
there at that point so let's relaunch
our uh OS but with GDB and what happens
here is like qemu sets up a GDB server
for us and then we can like connect our
GDB instance to it and start debugging
memory which is a pretty sick feature
honestly uh okay so what do we have we
have P star I and uh so if I look at
this guy
we should have uh the type is the first
thing in
here uh yeah so we have type is eight
that lines up and does our frame buffer
type line up as
well frame buffer type should be one
great um and then reserved is always
contain zero in the current version of
the spec so here we have do for buff for
type Reserve
zero um okay so let's look at the
address of this guy um so I think it's
I address
of
info do frame buffer red
field okay and let's just start printing
out
uh this like let's just print out like
seven bytes
here so
let's see what do we have
here uh so we have 06
8880 so this would make sense it was 168
8808 for red position green
position blue position right cuz then
the mask sizes are all
eight
um
so it's possible that like this color
info is off by
one so let's try to look at that so is
there
anything color type is defined as fall
it's 6
u8 is it possible that we're off by
one so if we we shifted our
reserved by one then everything would
line up let's look at our like type
definition
here
um so our frame buffer
info does he line up u32 u32 u64 u32 u32
u32 u8 u8
u8 then this like very
um so let's see what the size of this
guy is
um can we like maybe print somewhere the
size of the frame buffer info
PRP so here we can say a core M size of
of and we say frame buffer info
priv and the reason I'm doing is I want
to see uh if we are off like out of
bounds or sorry if the like size of the
struct doesn't match the
size the size of the object basic
basically
um so here we get the the frame buffer
info size is
40 and what do we get for the size of
the uh actual
tag so here we
have uh here can we just print out the
type and size again so we'll say print
line type is type and size is
size tet
run I guess we don't need GDB for this
test
okay uh so that's
up right we get size 38 is what we
detect but we think it's size 40 and
we're not aligned
right did I make a
mistake so this
is uh 8 16 20 24 28
28 29 30 31 32 33 34 35 36
37 uh wow there's we're all over the
place
here
4 8 16 20
24 28
29 30
31
two 3 4 5 6
7 um okay so maybe we have to pack
this so that now matches up
37 um and does this stuff match up red
field position zero red mask side zero
this is
still
right like we know that the red
field position is
16 and The Mask size should be
eight so I wonder if we just make our
reserved a
U6 which doesn't match the
spec um do we get something much more
reasonable red field position 16 red Mas
size eight green field position eight
green Mas SI eight blue field position
zero blue Mas SI eight like that's just
like much much much more
correct but like that that's true that's
what we've like determined is correct in
the multi one version of this
and our size is 38 which matches what
GDB
said or sorry not GDB uh matches like
what the header of our thing
says so I don't
understand something here is like just
wrong um
okay so what I'm going to do here is I'm
just going to
say note that uh spec says reserved
should be zero however when I parse the
color
info these values line like make sense
and are correct and with reserved of u8
it's total trash it's it's well we'll
say it's
uh
inconsistent inconsistent with itself
and
incorrect
okay um let's just delete all of these
comments
here I'm sure there's this like there's
a bug somewhere um but we'll just live
with this for now that's fine
uh which makes this implementation of
casting converting into our like uh
public version of
this that we export uh is going to be
much easier
now so let's go back to where we do
this and we're going to
return something like a initialized
structure uh his color size is is going
to
be what do we do in multi one here I
think this is in bytes instead of bits
for some reason I think that I just
thought that' be
easier uh this is still reasonable so we
we take the max maximum of RGB we should
probably actually just assert that
they're all the same now so we can say
uh assert that
equals uh what do we have here
um I do
hello where is
it uh red mask
size uh is the same as i. green mask
size and uh red is the same as blue and
then we return color size is I red mask
size
great
okay what else do we have here we have
red mask size oh this should be frame
buffer red
oops like this we throw a frame buffer
in there oops I had a space get that
um oops I didn't mean to get rid of
that either so then we have a green
field position so now these are right um
were my offsets in multi one in bytes or
in
bits they were in lights so here our red
offset is i. frame buffer red field
position
over8 this
is blue and this is green and here we
need to assert that each of these guys
is uh mod
8 so
here we have
red green and
blue
um okay now we have bytes per pixel is
just going to be uh
one or sorry no this is a frame
buffer
BPP by 8 and here we also want to assume
that frame buffer bits per pixel mod 8
is zero because we have we're working in
bytes our width is if frame buffer
width and the pitch
is pitch and the height is height and
the address is frame
buffer Adder
as all
right very
nice um so it's possible that this is
just going to work now uh I guess
somewhere we have to actually call this
and get it back
so all of the places in main where we
commented out the frame buffer we
actually are going to have to like look
at it now so let's go back to main
and uh let's
see and kernel in
it we're just going to do
this
um which means that here we're going to
do frame buffers equal
to frame
buffer
info uh this guy is using FR multi boot
one and we're just going to change this
to multi 2 everything else should just
work the
same um except that we have to check if
we actually get it so if let some frame
buffer
info ah we'll just expect it for now
fail to get frame buffer info
there we go so now we're just going to
uncomment all the places where we
commented the frame
buffer uh here we can bring the game
back and we can use the game
here and let's see if that actually
runs there we go very nice so we're back
at feature parody
very cool very cool I'm happy with
that
so frame buffer is now up and running
now there is a little bit of an issue
[Music]
where I I we did see last stream that
the like frame buffer
info is kind of uh how do I say
this it was in the memory area that like
could
be uh see like how do I say this uh the
memory allocator could in theory
allocate memory that overlaps with this
Frame buffer info stuff or like the the
multiboot info stuff but for now I'm not
going to worry about
that um because that was a problem
before as
well um so let's add you get add- you
get commit DM checkpoint multi boot to
boots
successfully with feature
parity all
right very cool so here we'll say that
we um fixed brick breaker game with
multi Boot
2 very nice and now we're working on
some
cleanup C multi2
stuff uh cuz probably we did a lot of
like the bed here um so one we
can remove multi
boot we don't need this at
all right we're only on Multi Boot
2 uh we'll cargo check
here uh in main
57 we're trying to use something that we
don't need and in
allocator we're also trying to use some
stuff that we don't need multi one great
um in Al when we're passing our
allocator the like multi boot stuff
we're kind of initializing the multi
Boot 2 thing directly here which we
shouldn't we should put pass in the
multi boot info here as a multi Boot
2
uh which means in main we call allocator
in it we should pass in a multibot
info
uh which should actually come from the
interrupt guard we should do this like
all the way up
here uh so here we'll pass
in like this great and now info here is
a multi
boot multi two and the allocator in it
comes with a multi Boot 2
info um
great uh we'll just CL here everything
else just works
cool um
um here we need pass info
great and I think the only other thing
here now is
to fix this guy now we don't have to
construct him twice um but we do move
him so we'll just
uh fix all of these guys to take him in
by reference because he doesn't actually
need to be moved
here great RX oh he needs to consider a
borrow here of course of
course and we go check great um C format
and can we cargo clippy is there
anything that the L is complaining about
actually surprisingly
not
um we'll maybe do a little get commit
here and let's kind of see what we left
our history looking
like um so I think I'm okay with just
folding everything down here
here and let's see what we've done since
the last commit
so uh we edited our qim wrapper to add
512 Megs of memory we don't need to do
that uh we can leave it how it
was so let's look again back up one um
so we switched our grub config to multi
2 I don't think that was required um
well it might have been let's try it
let's see so if we go to Grub config we
say say please boot with multi Boot 2
but really we could just B multi boot
maybe and Grub maybe is smart enough to
figure it out by looking at the
binary um let's
see uh no he actually does need the
multi too otherwise he doesn't boot all
right works for me so this guy says we
do two let's run them again and just
double check we're up and running
great uh what else do we
do uh um our allocator we added some
like printing to it and we don't need
that so let's back that
out uh so that was here we added start
and end we added start and end we added
print range and somewhere we probably
set the start and end on
initialization
here cool so that gets all the allocator
stuff out um we probably need to clean
up our boot dos stuff a little bit
because some of these tags that we were
using before aren't really needed
anymore so this was is like multibot one
stuff that we don't need uh the flags
are no longer part of it instead we like
pass in these tags directly uh this
magic is still the same but the check
sum is no longer
this
uh and here we can
probably put this these guys just down
here ah count to the top seems fine
sure uh so this is
the uh multi boot to Magic um and in
reality maybe we should like name this a
little better so we can say multi boot
to
Magic and here let's change this to uh
multi boot to
architecture
great um this is still
true
um the bootloader will search for the
signature and the first a blah blah blah
blah blah sure yeah this is true except
we just say that this is the multi 2
stuff
now check some is still reasonable size
set to zero gra doesn't care this is the
frame buffer tag this correct terminat
tag this is also corre okay I'm happy
with
that what else did we
do um our frame buffer stuff uses the
multi 2 stuff now
instead um our
main has like slightly adjusted how he
works with the multiboot stuff but he
also calls allocator print range which
no longer
exists um this in it looks fine we've
converted this to a conate instead of
taking an a of the multi info directly
because we want to parse set ourselves
as we construct it that's fine by me
frame buffer stuff looks very slightly
different but it doesn't really matter
um and what do we do
here oh sure our colel in it now takes
the multi magic as well so it can
validate that we're booted with multi
Boot
2 um and everything in here is pretty
reasonable I'm okay with all this Okay
cool so let's quickly just amend
this and say uh what switch from multi
multi boot to multi Boot 2 and why why
are we doing
this um as we prepare for multicore
support we need a handle to
the uh what do they call it in this like
giant list of jargon rsdp which is
the root
system
description
pointer this will
this is how we get a handle to the
advanced programmable interrupt
controller which is required for
multicore uh multicore
setup multi Boot
2 gives us
the point the
descriptor we need multibot one did not
upgrade to multibot
2
without uh without losing
any uh without making sure that we have
Future parody
great very nice all right so I think if
I run my lint
scripts that should
pass nice oh we do have a bunch of print
lines in there that we should have
actually removed so this is in
um probably in the multi2
stuff I didn't really look closely
enough
here status get add to you get commit
amend
cargo on the L script
again no
prints and we run
and everything's up and running
cool uh
so we are now in a state where we can
push so let's merge this in quickly make
sure that it's good and we'll push and
the remote side is going to quickly
validate that this compiles and runs
before pushing or accepting the
push and this is our kind of like shitty
version of CI we instead of asking like
GitHub actions to validate our code
after we push it we just like on our
machine we're pushing to a file like a
folder on our file system that's
mirrored to GitHub and he just says uh
hey if I can't build and run these tests
or if like my lint fail like you
I'm just going to like reject your
push um yeah but that's pretty cool
so let's try getting the acpi stuff out
of
here let's try it
so uh in the multi two
speec we can have the acpi old rsdp or
the new
rsdp I don't know what the difference
is let's see
so here he added
extended
descriptor
um which seems
reasonable is the extended descriptor
like much more
difficult let's look here
maybe
so what does he look like compared to
the old
version these look very
similar I think that those are identical
actually however there are many kinds of
all oh one the header which is come to
all St for each table is this so it's
probably the same where
um
we have like a list of elements and we
go element by element or something uh
let's
see so how do I parse this guy he gets
the header and he goes for
each element in length he looks at some
oh no that's not it he has pointers to
other
tables so he has his header and then
pointer to other sdt how to use suppose
I want to find the the fedit the fedit
being an sdt has an ACP I SD header its
signature is
faacp
ah okay okay okay
so for each element in
here
uh we look at the pointer to the other
descriptor table and we check its signat
and if the signature is the table that
we want then we know okay okay okay so
this is it does look
like if I'm understanding like this
chunk of code
correctly um we have
memory and in each of each slot of
memory he's going to each of these
segments here are going to
be
uh xsdt T is the root so where's the
struct xsdt come from here so each one
of these guys is going to have the
header
inside which is this
stuff
and ah okay okay okay okay so here we're
going to have like
header
header and then after that he's going to
have like a series of
pointers and each of these is going to
point to
a
another
header so he's going to point to like
basically another copy of this guy he's
going to be here here and here and the
data is going to be based off of
like what signature we see there
probably
okay that seems
reasonable that seems reasonable so I
guess what what's like a reasonable
thing to do here a reasonable thing to
do would be to print the signatures of
all the other tables that we see and
that's like a really good like
intermediate point where we could say
wow we actually like got something of
value out of
this so let's try to do
that let's try to do
that
uh which
means uh probably want to have like a
new area of
code let's call it
acpi
um and in main we'll just include this
module
cool
and oh I guess sorry the first thing
with to do is in our multi Boot 2 stuff
we actually have to get a handle to the
acpi uh root descriptor table
so this whole thing started because we
weren't sure if we wanted version one or
two let's do version
two which means that in our tag iterator
we are looking for tag
15 and here is going to return
sum tag of what uh rdsp 2
which is going to have a whole copy of
the rsds rsdp not
rdsp so here we're going to have item as
const uh
rsdp two
tag probably is a good name for
this
uh which means that we have to like
actually make this tag so this is uh R
what is it
rsdp and this is a
rsp2 tag and the reason I'm throwing tag
on here is because we're going to put
this actual rsdp somewhere else in the
acpi
stuff and so this guy has a size or type
size
he needs to be
reper he's a type and a
size and copy of
rsdp what the
uh that's crazy that the BIOS does
DHCP wow that's kind of neat so like in
theory I could like get an address in my
operating system without ever
implementing ghcp just cuz the BIOS
implements that's crazy or not
the BIOS the uh bootloader what that
seems like an insane thing for the
bootler to do am I crazy for the bootler
to like have an Ethernet
card driver oh sorry I misread this okay
so I was thinking like that would be
nuts if the ethernet like if the
bootloader had to have every single
ethernet car driver and do a DHCP thing
but instead it's just
saying uh no that's still crazy I was
even if this is like per like not
for
uh not for an actual ghtp response and
it might just be like configuration info
that's still nuts for it to be able to
interact with the network cards at all
what like an like what a large
responsibility for the boot have I must
not understand this correctly so I'm
going to ignore that for now but if that
if I get that that's crazy I would maybe
maybe this like this spec is maybe a
little much maybe maybe I have to like
request yeah whatever that's wild sorry
okay so here's a copy of the rsdp
here um so here have the rsdp 2 tag this
guy needs to imp
debug uh this guy has to be like
this
[Music]
and the the of him is going to be what
he's going to have the uh
rsdp
uh what we'll just say value or uh
descriptor is just going to be an
rcb2 and now we go into acpi and we uh
struct
rsp2 and then here this needs to be a
public struct and this guy has to
implement him so we'll
say
what
use crate acpi
rcpc
okay so this guy has to be reper C
and oh this is actually everywhere I
used rsdp I need to say rsdt
oops um am
I why is it called rsdp in some places
and rsdt in
others
oh rsdp and
rsdt are different
okay okay sure so what is in this RS DP
version two it looks like this so we'll
just
yoink
and
yoink
and what this is one two
8 nine this is going to be wrong this
needs to be packed I
think or else the alignment won't work
out and here we
just uh what do we do we make a Vim
macro where we delete this word we swap
the case here the
the case here we go to the end of the
word we put a call in we paste the type
again ah okay undo that undo undo
undo I made a
mistake uh okay new VI macro delete a
word swap case go ah
Vim macro delete word swap case go
to the end of the word put a CO in paste
the
word swap the semicolon for
comma all right that's close
um now we just have to fix these these
guys this is a uh
u88 and this is a u8 this is a u86 this
is a
u8 this is a
u32 um this has to have an underscore
here
this is a u32 this is a u64 u8
great uh and then this guy also
has
reserved is a u83 so let's double check
this now this is uh 8 14 15 16 so this
actually doesn't have to be packed
because it is lined
great uh let's derive from this
ebug um and let's
fix this and this to be snake case and
this should be Conor cool cargo format
because that's butchered fixes
everything for me nice and uh
now I guess we'll just do the same thing
here we'll
say
uh we're going to call this what get our
DSP
rsdp this is going to
return
RS
dp2 probably I don't know and if this is
RS
dp2 we'll print line it for
now for for debugging purposes but later
we're going to actually use
it and in main now in our like kernel in
it or
something we can just print it R DSP so
we'll just go down here
uh and we'll
say
info uh get
rsdp C check do we build no because we
spelled something
wrong here we said item instead of item
great check car run do we get something
interesting out of
this uh so he never printed it that
that's
weird uh I guess we never saw this
tag so I guess we actually do have to go
back to our tag iterator here and what
I'm going to do actually just for fun
this time is instead of adding prints
here I'm actually going to go in here is
that a breakpoint in each of these and
say for each
breakpoint uh
print
where where was I looking here I'm going
to
say I guess I want the break point to be
here what line 105 and I'm going to say
print the type and print the
size and
continue and then if I run this the GDB
GDB it's kind of fun I just get
to
um yeah look that's pretty fun so for
each of these I get to print it so I'm
looking for
the I'm looking for a new rstp typee
15 um we can get a little
crazier um and say dprint
F
Type uh integer size integer and I think
you can say like tip
size I
think
uh
I think it's like this so I say make a
break point at
this
this location with this string with
these arguments I
think we'll have to double check this
it's been a while it's been a while so
let's do GDB equals 1 C run run the GDB
script format string required so I think
maybe I have to put comment coms
here set
spaces
format man de print F help de print
F I want it to work cuz it's so
cool
um location format string arc1 Arc
2 so we have location format string
maybe we have to get rid of these spaces
or else gets
mad ah there we
go there we go hey isn't that kind of
fun so without actually recompiling
anything uh we do get these like kind of
like nice print F style things in the
debugger I always thought that was kind
of fun um so I'm noticing that none of
these are type
15 right we do have type
14
um so I guess I just don't have acpi
2 that's kind of
surprising so uh can I look up Q emu
acpi
2.0 there's always
ovmf so it might just not support
it
ah so it uses Coss which is too
old okay
okay so after all that after deciding
that I wanted version
2.0 it we don't have it all
right okay okay okay I should have
checked that
earlier that was stupid I should have
checked
so uh we're going to take out all these
twos um and then I'm going to go to the
acpi stuff and I'm going to take out all
this
um this guy doesn't have a two anymore
and this guy doesn't have a two and this
guy doesn't have a two we're oh we're
going back to RS dp1
baby um here we have a two so this
should be this and this should be
this and somewhere down here I have rb2
so this should be rb1 this should be
rsb1 and instead of 15 we're looking for
14
um oops uh can
I write volatile that requires the
pointer
is oh that's
weird uh is this because of
GDB okay so we are on the Brit
side we do have the
rsdp is the signature
correct
um
RSD
pointer 8 by string not alternator so I
guess uh we should convert this to a
string and take a
look so down here we can see is this
valid so we'll say
uh we'll say what P
dot header was it what do we say the
value inside was
descriptor and
signature Sig
ner and we'll just say core uh
stir from utf8
unchecked so let's just see what if this
guy says what he's supposed
to and this is a private field fine so
you can just kind of like off pub
great and here we need bar
sure okay so this is good we are seeing
RSD pointer like it says we should um I
am curious about where this right
volatile unaligned is coming from so
let's kind of take a look at
that
um so I think that what we can do is we
can go to our main and look at our Panic
implementation and here just put a break
point here so we'll say
uh run. GDB
break point at
this and then when we run with GTB
equals 1
uh see uh we look the other thing I want
to do actually is I want to support
reloading so we're just going to say
like delbr
here uh okay so GDB DX on
GDB okay so where's this coming from
this is coming from game clear screen
set
pixel oh that's
interesting why all of a sudden is our
frame buffer not aligned it was a second
ago uh there's probably a mistake in our
like packing somewhere I bet you if I
run release this
works uh which means that
here I need to edit my GDB script to use
the release version
yeah so there's pointer alignment issues
in debug only either either there's
pointer alignment issues in debug only
or we're only checking for pointer
alignment issues in debug I actually
don't know which one it is
um okay but that's something to come
back
to
uh I want I want to put that on the back
burner uh because I want to keep going
on this like RS DP stuff okay so we've
we've parsed the
rsdp um we can te check the revision
field um which we should assume is zero
but I guess if we're if we don't check
the field and we get like version two
but we think it's version zero version
one uh that'll probably still be fine
actually
because I assume version two is
backwards
compatible
um before the rsdp is lied upon you
should check the checkm as valid you add
up every bite in the structure and make
sure the lowest bite of the result is
equal
zero um so you add up every bite in the
structure and make sure the lowest bite
of the result is equal
zero oh I see so the check sum is just a
value that will make that
true
okay um
oh this is supposed to be
packed according to this so let's go
back to
rsdp and let let's actually put a packed
on here and I do actually while we're
while we're throwing packed on
stuff I guess it does make sense for us
to throw a packed on this guy oh he is
packed all
right we might want to just like put a
pack on everything in here but whatever
we'll come back to that ah I was trying
to avoid looking at the frame but I
can't help myself I can't help it I
can't um we'll print the
address in both debug and release and
we'll
see
um so we'll see if these are the same if
they're different then there's something
like really wrong otherwise it's uh fine
well not fine but
uh we'll think about it so here we get
FD 000000 in
release we get the same address in
debug
um that's really
interesting it's really interesting so
let's maybe see if we can um oh I can't
help myself I can't help myself we have
to debug it we have
to we have
to so uh let's look at the GDB thing
script we put this back in debug we have
our Panic thing set so we can just
probably GDB DX run our script back
Trace look back to uh this right
volatile and see what we're actually
trying to do so that's
frame six and we can say what address
are we running to that's definitely not
aligned
okay so why the is that
happening
um so let's look
at let's look at the code here so here
we're saying Adder is off something
offset so P offset
three p row P self. info.
[Music]
pitch that's crashing for some reason
1920
uh what else is happening
there uh the self do bytes per
pick what the 128 that's
wrong
Heights per pick is
128 whoa whoa whoa whoa whoa
whoa whoa whoa whoa whoa okay so we
run we
Source run. GDB
we print i.f frame buffer bppb
24 so that should be
three uh it could be that like sometimes
when you like get into these like Panic
things sometimes like the stack doesn't
restore itself
correctly
uh is the frame buffer supposed to be
hacked is it is it is it how do I say
this I thought that the when I saw this
before I thought we were doing
32bit values
but packed into 24-bit depth but I guess
not
so
uh I guess we actually do have to do
something more like
uh we can't write the whole color at
once
um unless in our boot script can we ask
for 32bit
depth
maybe does that build and compile and
run
so what do we get
here
okay uh so we get 8 bits per pixel Let's
uh hit continue and
see all right cool so that's just like a
little bug there that we accidentally
made where when we asked for 24-bit
color depth
um it was doing the wrong thing but it
was like giving us uh 24 bits of color
which is like the same as when we have
32 bits except they were 24bit aligned
24 yeah which so it was just three BTE
aligned which makes like the efficiency
of using this lot worse so if we ask for
32bit depth it'll still give us 8 bits
per pixel but it'll align on 32-bit
boundaries which makes like the rum
color is much
nicer all right cool okay so we uh aside
fix bug in
frame buffer pointer alignment this is
0136 and
uh don't know when we started
okay uh so we're back to trying to read
the uh pointers the root system
description
pointer um so we want to do checks and
validation uh so in multi boot
probably uh
maybe
in uh sorry one
sec in the acpi stuff we can do maybe
imple here and we'll say function
validate check
some and I guess this will turn a pool
and we'll say
uh for B in self. Sig self this takes in
self obviously so we iterate the
signature and we say uh let act equal
z
um and instead of I was going to iterate
over each field manually but instead I'm
actually going to cast this whole thing
to a bite array so we'll say uh let
pointer is equal to
rsdp I guess
self as const 8 or I guess as const
rsdp
and then we say p is p as
con8 and then we say uh for I in0 to
uh core size of
[Music]
RSP uh we say act plus equals p. add I
and we dreference
uh here
great and I guess we call it we're going
to say that this is a
zero uh u8 and we're going to say this
is a wrapping
ad
great and then here at the end we can
just say
uh act equals
z is if the check is
valid uh so now somewhere we can say RP
so probably in the multi so for now
we somewhere try to get the RSP and
we're just going to say print
line p. validate
checkm and we'll say here
checkm valid is
this um really uh this is p. descriptor
validate check
on and this is a private method so we
have to make this public
great uh and then we cargo run we don't
need GTB
anymore let's just see what we get uh
attempt to add with
overflow uh right
so oops this should be act. wrapping ad
this
oopsies
whoopsies okay so check sum is valid we
are big
chilling
um
so now we can look at the rsdt address
and that will be the address of the
rsdt
um okay so what the is an
rsdt
um here is the rsdg
[Music]
header and and what happens in case you
have use rsgd
pointer so we have
signature length revision check
Zone okay then we have the OEM ID
revision Creator ID create revision
okay ah here we go this is the same
actually this looks very similar so here
they rsdt it has pointers after the
header to the next one so this is like a
link
list um
we don't have X sdt we only have the uh
shitty version
So
Okay cool so this is easy so let's uh
yeah let's try to get let's try to
print every
single header
signature so here we pull this
guy um and we do do our Vim macro again
so we what delete a word go to the end
of the
word paste the type ah wrong button
so we B macro delete a word go to N word
colon paste
type
replace
uh the semicolon with a
comma and we do that for all
these and here we go all of these and we
say we want them to be lowercase
and this is
OEM ID OEM table ID
OEM
Vision Creer ID and
Creer uh revision like this this type we
need to convert U 32t to
u32 uh 8 T to
u8 uh car to
u8 and this is a u8 as well and we need
to fix these array types so rust arrays
look like this so like this like
this and this is need semicolon
okay so we also probably need to reer C
and pack this
so so that uh it matches
the the format in memory like
precisely
um
okay and
now uh we can do
this so here we
have this guy so he is the header is
like
this and then here he has pointers um is
a uh unknown length
array
so I guess this is just a
uh we'll call it a
u32 and in our implementation for this
gu we'll make a
function called uh
what we'll call it print headers for
now
and he's going to take in himself he's
going to say uh let length
it's equal to self. header.
length I guess we don't have to do that
and then we'll say uh
let uh po pointer pointers is going to
be self. pointers but he's instead of
going to be a Uther is's going to be an
address of the Uther
2
and I guess we're going to say
uh for I in0 to length over 4 because
the length is in byes not in uh whatever
this
is oh we're going to say p. add I you
reference
that and we'll say
let
uh what child
pointer equal
this
um
yeah um this needs to be as con C
through
2
and this needs to be U size like
this probably this is unsafe so we stick
an unsafe block
sure and we cannot divide u32 by U size
so actually like this
very cool okay okay okay okay
so then what are we going to do we're
going to try to get the signature from
each of these
guys yo yo what am I working on um okay
so there's a little bit of a rabbit hole
here we're trying to enable multicore
support and to enable multicore support
Port we need to get a handle to a um
Advanced programmable interrupt
controller
um and to get the advanced programmable
inter controler Handler we need to parse
these like acpi tables which are like
this like cross I I don't know whose
standard it is I think I saw like to
what H it's it's here
somewhere
uh
standard Intel Microsoft Toba made this
standard which is like uh basically your
way of like enumerating Hardware kind of
uh so like the BIOS will like give us
this table and it will like tell us
things like how many CPUs we have where
I have like interupt controllers where I
have blank like there's just like a
bunch of like things that it'll tell us
about as far as I understand and if you
like are on Linux and you go and look at
like CIS acpi I think that you have like
there's just like a bunch of in
there it's like power management
protocol as well as like Hardware
generation so what we're working on now
is en able to get multicore support we
are trying to parse the acpi table so
that we can find the programmable
interrupt controller handle that we can
turn on the
CPUs um and right now we're just trying
to prove to ourselves that we can in
fact parse this acpi table and at least
get like a list of useful
strings um okay so for each of these
children in the
table we're going to convert this to
a pointer to an acpi
header um and let's just print the name
of like what's let's just print
the signature so so we can dreference
this and look at the signature and let's
just print
line
uh for format from utf8 unchecked
because I don't really give a if
it's
wrong uh this should be corer actually
go and here I need to borrow this guy
like
this um okay so now I just have to like
actually get this rsdt from the rsdp so
I guess it's like a pointer to the table
and here we have the address so probably
in my multibot
St
um we can say uh let
rsdt is equal to the descriptor do rsdt
address as a cons pointer to an
rsdt and then we can say rsdt print
head and let's take a little piie so
here we need to
import
d uh which is private so we need to go
into the acpi stuff and back this
public oh God you're such a neag rust I
get it you want me to be safe but
off okay here we go and now we cannot
print this without Dre referencing this
guy
okay and there's like a very good chance
that this just crashes but it be
cool if we just got a list uh yeah so
here we're already um so we're
doing a misaligned pointer D
reference um that's probably this guy so
maybe here we just say reer C packed I
should have done this from the start I
didn't realize I
hadn't
um reference to pack field is unaligned
pack stes only aligned by one p blah
blah blah so
so here I actually
should um does that actually just not
build how do I assert that this is
aligned is there like a is aligned or
can I
like does it just not let me do
this if I say that this is a u8
ah
off uh pack STS are only line one bite
so I guess just we'll write that this
isn't packed and just hope to God that
this
works um but it might not there's like a
good chance it doesn't so let's see uh
Miss line poter D reference off
okay
um so how do I make sure um I guess
maybe I can make
this
a null type and pass this to this guy
and say let p is equal to p as
[Music]
232 okay that gets me
somewhere um that is still going to
crash okay so now let's actually start
running with
GDB and we can start seeing um where
we're going wrong
so run.
GDB um
and where are we crashing we are
crashing in print headers as
expected and here it's p. add I as star
sure okay so that makes sense this is
acpi line 56 is there a goal with making
this
OS uh not like a concrete one I think
that uh generally I find it easier to
learn about stuff by doing it right so
like yeah if you make if you write
something you're going to understand it
pretty well in the same way that if you
like explain something to your friends
you you must understand it better than
if you just read it and thought you
understood it um it's kind of fun good
stream
content uh I've always wanted to yeah so
I the all of that kind of saying that
like we don't really know what this OS
is going to turn into we're just going
to kind of like just make stuff and see
where we end up um
yeah okay so here I've got a misalign
pointer difference frame three so let's
look at where what am I trying to do
here again I don't even
remember uh I can't backround
this um so this
is p. add I as
consist
so
uh okay so let's see we have p p do uh
sorry I have to for ground percent two
so doesn't work um what's I here Pi I I
is
zero p is this whoa oh
oops
okay um so already this doesn't look
right um so this table
I'm supposed to have this header then a
u 32 array of pointers to other
sdts um where I have
h.length minus size of H over4 so I've
already kind of that up I didn't
do this but these point this pointer
list should be walkable I guess if the
acpi sdt
header uh how many is this 1 4 or 1 5 6
7 8 oh
four + 4 is 8 10 + 6 is
16 then this is all 8 by line so this
should be 8 by
line
um where is like rsdt here
EA um so so is that eight by
aligned
no I see so our whole descriptor table
is not aligned which means that we can't
just access these
pointers
oh that's
annoying that's annoying all right so I
guess
uh that that's reasonable so here we're
going to say that this is
like
uh pointers goes like this so for each
of these instead of dereferencing these
directly we have to say
uh we can't D reference it but we can
mem copy it out so we can say let
pointer child
u32 this is child pointer pointer is
equal to a mem copy of this
out so how do I how do I do that I think
I can
uh
P so I have the child pointer pointer as
conate I copy this out so I say what
core M
Copy um
transmute copy interpret sources having
the type desk then read source that
moving the contain
value maybe this is what I
want so here I have
uh a
what H maybe I just use mem copy I think
I have
colel
rate liy mem copy and and I can say let
child u32 is a u3 uh equal
Z and here I can say the destination is
uh child u32
as on8 oh my
God and the source
is uh uh child
PP as conate and N is
four uh here I need to make this mutable
and this needs to be mutable and I have
to actually cast this to a mute u32
first okay and so now I should be able
to look
at uh this we should be able to say let
child
p is equal to child u32 as const
acpi header God damn that's
complicated uh let's try this again and
see if the missile line pointer aises go
away
hey that's pretty
sick look at that we have these are like
valid valid signatures very
cool um we were still broken right
because we're crashing but
um let's take a
look so we're getting a lot farther
we're actually getting at uh frame
15 at acpi
60
um which is coming
from Panic unwind slice itter into it
right string yeah so there's something
uh with this from utf8 unchecked so
probably uh this length has to be minus
one or
length oh this is just
length as U size uh this is
length
minus something
think self
dot uh size of I think core
[Music]
MIM size
of a CPI sdt
header there we go and this should be
length as you size minus
this okay let's see if that fixes
it
let's go that's so sick Okay so
we've have in fact iterated over all
these acpi tables and we are seeing
uh what is w t or
HP let's see if each of these is valid
so ack is definitely the one we're
looking for right we're looking for the
advanced program interrupt controller
thing uh
FP is this guy what is
HP oh high Precision
clock oh yeah I've been want I
wanted to get this guy too at some
point sick and then what's
W
um Windows ACP emulated
device woo okay that's pretty
sick um I'm happy with that I think
uh that's enough for me for now I think
I'm pretty happy with that um right if I
was going to keep going I'd go for like
another 20 minutes probably and I don't
really think that I have anything that I
want to really accomplish in those next
20 minutes that's like short
enough um so yeah I'm pretty pretty
happy with that I think probably
tomorrow we can keep going and maybe
maybe we'll go on the uh AP pick or
maybe we'll look at the high Precision
timer because um I have been kind kind
of noticing that the uh the 4
millisecond tick rate is not very good
and when I was reading some of the
multie initialization stuff I did see
that like we do need a more precise
sleep than that
probably um so I think next stream we'll
look at either the hypers timer or the
advanced programmable inter interrupt
controller um today we got pretty far we
got to the point where uh we started
from multibot 2 headers not prop not
being properly parsed we fixed our uh
Multi 2 parsing we got Future parody
with our multi one
implementation um and so then we we
started reading the acpi tables that are
provided to us by Multi 2 to the point
where we we know that we're at least
like finding the tables that we we want
to see um yeah so I'm pretty pretty
happy with that um if you liked what you
saw you can always tune in I stream most
days on Twitch or around like one or two
Pacific time for like one and a half to
two hours and if you miss stuff you can
always catch up on YouTube uh YouTube is
linked in the twitch description and if
you're watching on YouTube and you want
to pop in and say hi uh feel free uh
twitch twitch descriptions Linked In the
YouTube description um yeah so thanks
for watching catch you on the next one
bye