 The second demo and please be quiet everyone, some that we might be able to hear what's actually going on. No way to hear what's going on. I'll just have to sort of narrate. Again, the serial console, this is one of the GLLX boards, an AMD CPU. The embedded, AMD embedded CPU with 256 megabytes of RAM. And let's see when I reset, let's go with the reset. There we go, core boot running. And there it's already starting the Linux kernel. And that's the final prompt of the Linux system, which is full up at that time. So this shows that if you disable all the debugging stuff and you have a really trimmed down kernel, you can get a very nice startup time. And talking about boot time measurements, I think it's important to be careful with the numbers here or just be careful about what the numbers actually are saying because different people will use different metrics for boot time measurements. And of course everyone wants their numbers to be the best, so they're going to use what is best for them. What is this time measurement actually saying? Is it saying from power supply connected to Windows running with a full desktop, whatever login user or Linux or whatever you have? Or is it from after the mainboard power up sequence, which might make a difference? It sounds silly, but it might actually make a big difference. There are about 30 voltages in a PC system, and these all need to start in a special sequence. And that takes time, of course. Or is it from the first instruction fetch, which might be a lot later than after all the voltages are up? Who knows what's going on in the system? So the guy who's been developing CBIOS, his name is Kevin O'Connor, he did some optimizations for his particular board. He has an API board of the API CN with a C7 CPU and the CN700 chipset. He put Corbuth and CBIOS in Flash, CBIOS is the payload, and he had a grub on Asata SSD. And this is the results he got. It's been 350 milliseconds just waiting for what seems to be power sequencing. From the time he presses the button to some software actually running is almost half a second. Then he measured that it takes about 50 milliseconds to wait for a communications bus on the mainboard to stabilize. Another 20 milliseconds to configure the memory controller. 10 milliseconds running Corbuths. 200 milliseconds waiting for the VGA BIOS to initialize the graphics. And another 10 milliseconds in grub. And the grand total is that it takes 750 milliseconds from the time he presses the power button to when Linux is already starting. Security slide, I don't know. I think I'm going to skip this. I'll maybe just mention it quickly. Corbuth attack, there was an attack made public I guess the year before last year, so 2008, where even though you power down your computer, the RAM might not be completely empty. And if someone can steal your laptop or desktop for that matter, they can take out the RAM, the DIMM, and extract all the contents of the data. And it's really easy to find crypto keys and so on. So Corbuth can be used both in the attack and for defense here, because Corbuth has RAM initialization. It can start the memory controller and then have a special dump routine inside Corbuth to read out all the contents without changing anything in RAM. But you could also use it so that when you're shutting down, there's a part of Corbuth which runs and makes sure it's to clear all the memory before it powers off. Code injection into the operating system. There was an exploit published where part of the BIOS was changed to always rewrite permissions on a particular file in the root file system. So whenever you rebooted, this file became world executable with plus s and everyone had a root shell on the system. That's not something you want in your firmware. So it might be worthwhile to look carefully at the firmware you're running. There's a lot of good stuff about Corbuth. You can get really fast startup times. It's open source, C code, TPL. You can audit, you can read it. You don't have to study assembly sources a day on end to go through the code. We have one tree for all the boards. So there's a fair chance of reusability and extensibility there. There's still some challenges. We need more testing. That would be great. There's a testing infrastructure, but it's kind of difficult to hook up boards to be tested to this infrastructure. So even though we have really nice way in this infrastructure to test each commit on actual hardware because the fact that it's too difficult to connect boards to this infrastructure means that there's little testing actually done. Everything is built on each commit, and that's a good start, of course, but it would be very nice also to see boots testing because stuff can rake even though it compiles, it might not run. And it would be very nice to have all the boards really 100% supported. Most of the boards are implemented by one single developer or a small group of developers and they were really happy when all the stuff they need is working, but that might not be enough for everyone else. So little things on the main board might still need some code to work. Most boards are not really far away. There's only very small, very small stuff missing. ACPI, we need to get better at ACPI, but we already have a lot of good progress there, and thanks to Rodolf who's going to talk about it a bit later, and actually have fun also. And code is great fun, so come into the project, please. Thanks to Luke for organizing this dev room and some links, code.org, and we have a mailing list, and we're on IRC and the Wiki, you can just add anything after the URL and you should get an informative page. Questions? Question, yeah? What do you use for flashing your flash chip if it's completely screwed? What do you use for flashing your flash chip if it is completely screwed? Commercial flash chip. Sorry? Do you use some commercial flash chip program? You can, yeah, sure, that's one way. You can have a flash programmer or a flash writer standalone. That helps, but you don't always have access to that. One thing you can do is to use another main board instead, and hot swap the flash chips. Flash chip programmer. Good to have, but... You can also use another main board. Yeah, hot swap, that's fine. I think Carl Daniel will talk more about that also in the flashroom talk. Another question, yeah? What are the implications of not fully supporting ACPI? What are the implications of not fully supporting ACPI? Yeah, sure. Rudolph wants to answer. Perhaps I'm the right guy, so that's your question. But it's supported to the moment that everything, the line of needs is there. Everything with those needs is there. So both is that good. All is there. Everything is properly everything. So what we did is somewhat minimalistic ACPI implementation. This was the standard one. It's there. Nothing more. So we don't have much of the byte code stuff there. We have just only very basic routine what is required by a standard operating system. So in this case, everything which the real life operating system needs is there. But there is no consistent like the terminal zone and late and so on because it can be done either on some platform level by some other drivers and so on. So we don't need to be full-blown, madness, ACPI. And there are, so I guess I could add there that one implication would be that there needs to be a driver to handle some tasks that might otherwise be handled using ACPI on another operating system or, sorry, another firmware. But again, if Linux has that driver and you want to run Linux, then it's fine. No more, yeah? Okay. Another question? So your program, your first instruction that will be ever done is immediately output. Yes. Yeah. I presume that you have to configure output to say which serial port you are using. Yeah. Things like that. Yes. Yes. So you can configure the build and there are also some variables that are set or some settings that you can change runtime. Well, not runtime but are read from NB RAM. So if you boot up your operating system, you use NB RAM tool to change the settings and the next time you reboot, they will take effect. Yeah. For example, there's a new motherboard with, I don't know, newer version or a higher clocked RAM version. How can you extract the exact parameters? So a new main board with higher clocked RAM or a different type of RAM would be small to medium effort. Rudolph is also going to talk about porting coreboots to a new board and it would really be like adding a new main board if it's say an upgrade from DDR2 to DDR3. Not all of the work needs to be done as if it was a completely new main board but still some things have to be changed. And like for the RAM, in order to get the RAM stabilized to be read, is it some sort of file? So I'm going to talk about that in the next presentation of RAM initialization if you can spot the points. If you're, are you staying for that as well? Then maybe, okay. Well, if you have, then maybe we can come back to the question. All right. Yes. There's one laptop supported at the moment, two if you count the OLPC. So the laptop that is supported is, I mentioned that in the presentation. It's, the development was funded by the German BSI. And it's a rugged laptop but the components in it are fairly standard. So that code and that effort can be reused for supporting other laptops as well. And I also have one board that I'm, I'm sort of working on a laptop. They call it a netbook but I, it's a 12 inch. It has a 12 inch screen so I don't know if I think it's a network. But this is, this is the board anyway. This is all that is really in the laptop except for the screen and the hard drive. It's a VIA based platform of the Samsung NC20. So hopefully that will, will work at some point as well. Does that answer your question? Please do, but it, it might be a lot of work. And especially it depends a lot on the, which components are in your laptop. Rudolph will, will talk about that more also in his presentation. It can be really difficult to find out all the information that is, is necessary. All right. So no more questions. Thank you very much for coming. Sorry, I, I went over time a bit, but yeah, I hope you thought it was, was interesting. Do we need a break between presentations before I start the next one, or should I just go straight away? All right. I'll continue then. Okay. Yeah. So core boot and PC technical details is, is the title of this presentation. This is what I, I hope to, to be able to talk about here. Who am I again? I guess that's the same as, as before. A look at the 30 years of PCs. The PC has been around for a long time and it's changed quite a lot. I were to have a look at the Isobus, the, the first. Well, actually the second extension bus in the PC, but it worked the same way as the first one. So we're going to look at that in order to learn some things that are very important and still apply it to a lot of other buses and devices in a modern PC. Some thing about hardware registers, various, on various buses, ISA, PCI and MSR. I'm going to talk a bit about the RAM. I'm going to talk a bit about interrupts. RAM initialization, cache as RAM is a trick that is used by many firm, firmwares today. GCC and ROM CC, ROM CC is, is something that came out of its core boot as well. The different x86 execution modes, real mode, protected mode, dimension mode. Maybe embedded controllers if there's time and the thanks. This is the same as the last slide I've been doing core boot for a while. I started in Hamburg and I do stuff. The PC in the 1980s, it might have looked like this. There was a CPU and there was a boot ROM and there was some RAM connected. And it was a cassette player and the keyboard and an expansion port. And all of this was really connected to the same sort of same communications bus. So we went from cassette to DDR3. And this is what the PC might look like today. And there's a lot of stuff in here. We can have four or however many, eight, sixteen CPUs maybe. Every CPU might have its own memory controller. And the RAM is connected to the memory controller and that's one bus. And the different CPUs might be connected together in one special bus. And then there's some connection to the North Bridge and some IO, IO stuff. There's a whole graphics block which is either in the North Bridge or might be on a PCI Express bus somewhere. There's another bus down here to something south bridge which has a slower, the old PCI bus. There's some USB and IDE. PS2 maybe there or might be over here in the Super IO. LPC is a replacement bus for the old ISA bus. And it's, I would say that it's really on every main board these days. There's an LPC bus somewhere. It can connect to a Super IO. It can also connect to a boot flash or there could be an SPI bus which connects from the south bridge to the boot flash. Or there could be an SPI in the Super IO. So it goes from the LPC over to the Super IO to SPI and then to the boot flash. And the Super IO has lots of other stuff also. Floppy and it could be PS2 as I mentioned. Serial, parallel, GPIOs, watchdog, thermal measuring lots of temperatures on the board. And there might also be microcontroller. So another CPU inside the IO chip down here. That's the embedded controller that I hope to rant a bit about also. Oh yeah, and there's the SM bus. I mentioned in the previous presentation that Kevin had some issues waiting for the SM bus to stabilize. We'll come back to that when we're talking about RAM initialization because it's connected to the RAM. So this is a look at how it might be and it can of course be even more complex. You can have, this might not be a single core CPU, but it might be a four core CPU. So you have four CPU cores behind that one connected to one memory controller, but connected also to all the other CPUs and it can be pretty complicated. So HG is hyper transport, that's AMD's bus for interconnect, or AMD's interconnect between CPUs and IO nodes. Intel developed their own. It's both quick path interface I think is the abbreviation, the QPI. That's the same thing, connection between many CPUs in a system which has many CPUs. So what about this ISO bus? The way it looked back when? There's IO and memory access in the x86 CPU. It's an 8 or 16 bit data communication path. And depending on if you're doing IO access or you're doing memory access, the address space has a different size. So for IO, it's always 16 bit, so you have 64K addresses. These addresses, they're usually called ports. I'm not sure why, but that's if you see ports somewhere, it's about an IO. The CPU instructions used for IO is INW, OUTB, OUTW, and in newer CPUs you have INL and OUTL instructions also. These also are available as function calls in Linux. You can direct IO from Linux user space if you do some preparations first. I think Carl Daniel might talk about that also. Well that knows, in the lightning talk I guess. For the porting in the ELT OS room. Well anyway, it's possible to do this direct IO communication, these IO accesses from Linux. Even if there's no ISO bus in the system anymore, it's still possible to do these operations. And where are they going to end up? Well they will end up on LPC usually, and there might be something listening there. Typically the super IO is what you want to talk to in that case. If you're doing memory accesses, then you have 20 bits of address. And we'll have a look at how those 20 bit addresses are created in a bit. In the execution mode, stuff and the memory accesses, they all use move instructions. So it's just memory read and memory writes. If you're programming in C, you're reading from a variable that's a memory read. In the really early PCs, that memory was external in the new PC. The memory is actually connected to the CPU itself. And of course has a lot longer address space than 20 bits. There's a whole bunch of registers in all the hardware components that we looked at and in every add-on component that you can connect to a PC. And these register accesses, they will be either IO or the registers, they will either be IO mapped or they will be memory mapped. On ISA hardware, it was kind of common on the really old, for example, really old networking cards. You had a whole bunch of jumpers, how many people remember those? Yeah? You had to choose the base IO port and you had to choose the interrupt to make sure there were no conflicts and it never worked. They invented this plug and play stuff which was supposed to be clever, but I don't know. In theory it was good, but I think the implementations weren't really that awesome. PCI is very different. There are no jumpers, there's no conflicts. The firmware handles all the configuration. So Corebuild does all the long printouts that we saw from the first demo is checking all the PCI devices connected to the system and making sure that they can coexist and be accessible at the same time. PCI devices, they have what's called configuration space, 256 bytes of registers. They are always reachable. I think the standard says that it's not necessarily always, but in practice it really is always. They are reachable on IO to ports CF8, hexadecimal, and CFC. This is an index data combination, so you first write the address of the register you want to access to CF8 and then you do the actual value access on CFC. Say you want to access... No, I'm not going to give you an example, because you have to encode the PCI device address and something that's called a function number and the register number into this access to CF8. I can't do that in my head, so we'll have to skip that example. Anyway, first specify what you want to access and then do the actual access on a different IO port. This is typically always available. If the system has PCI, then this is going to be there. This is called the type 1 configuration interface and maybe you've seen that in the Linux kernel sources. You can choose what type of configuration access method that's going to be used. This is also what CoreBoot uses. CoreBoot used to support another access method, but it was never used, so we threw that out. Configuration space can also be reached via memory mapped registers and that's called MM config. Not every system supports it, but if they do, it's more convenient because you just access what could be a memory address. It looks just like any other address in memory, but there's no memory there. Instead, you're reading and writing. Well, there is memory, but the memory is small registers on some PCI device and it's not the DIM, the main RAM in the system. That's handy and it's also faster. These IO accesses tend to be pretty slow because they are so old and legacy compatibility stuff on the bus. The 16 first bytes out of these 256 are standardized by the PCI standard. Every single PCI device is going to have the first 16 bytes exactly the same. Well, not identical contents, but identical structure. The first four bytes show the vendor and the device ID, for example. There's also information about which interrupts is going to be used for this device and a couple of other things. Interrupt polarity detected errors on the PCI bus by this device. If this device is a bus master and a whole bunch of other settings as well. And there are base address registers or bars, as they're called. So maybe these 256-16 bytes, these 240 bytes, maybe that's not enough for doing everything that this PCI device can do. Maybe you need a lot more. If it's a graphics card, for example, you want access to the graphics memory. 240 bytes isn't really a lot of graphics memory today. You need some way to create a window into the graphics memory that is on the graphics card. So then you will configure a bar or when the firmware will configure a bar, a base address register. Saying to the PCI device that when the PCI bus sees an access to this particular address, then that is meant for you. So every PCI device looks at the traffic on the bus and only the one that has been configured to access to this particular address is going to accept them and decode them and process them. So in case the firmware does a half-assed job and sets up base address registers which conflict, then you're going to have more than one device react to stuff going on on the PCI bus and nothing is going to be working. So in the example of a graphics card, the base address register would set up memory mapping because you want the graphics memory to be accessible as memory. But base address registers can also be used for IO mapping. In that case, you have some number of IO ports that you want to end up on this particular PCI device and then you view the firmware, set a base address register in the same way which tells the PCI device to decode accesses, IO accesses to this particular port. This is really common for PCI devices to have one or both memory and an IO bar. It could even be several. I think in the 16 standard bytes, I think there's room for four base address registers. Sorry, it's in the full 256. It's room for four or maybe even more base address registers. So you can have one PCI device that has several different memory regions or IO regions that it's decoding. There are also the MSRs. Almost can't see. Model specific registers. That's low-level registers in the CPU itself, in the North Bridge, in the IO controller. Stuff like that. I'm going to come back to some of those. NVRAM, I mentioned that. It's also called CMOS. I probably don't use CMOS technology anymore, but the name has stuck. In its simplest form, it's 128 bytes of battery-backed RAM, and it's stored in the real-time clock chip. The real-time clock chip, in turn, is usually part of another chip in a modern PC. But in the original PC, that was one Motorola chip on its own. Now it's usually in the Supri-O or maybe in the chipset. So these 100-odd bytes, they survive power-down. You can have the system disconnected forever, or not forever, but for a long time, and the contents is still going to be the same. Also, the clock keeps ticking. Of course, when the system is shut down, that happens there. The standard way to access these registers is, again, one of these index value IO sequences. You write the address you want to access to port 70, and then you read or write port 71 hexadecimal to read or write that value. And this is where all the BIOS settings are stored, typically, and this is also what MVRAM tool messes with. So you give it the layout file of which bits are which setting, and it will do all the translation and make sure you don't overwrite any wrong bits. It accesses these ports 70 and 71, and it works out well. There are also extended registers, another 128 bytes, and there can also be another 256 bytes in other places, but that works just the same way. Ports 72 and 73 are really common. If you want to have a look at the driver for this in Linux, it's driver's car, MVRAM. Somewhere in ARC x86, there are a couple of macros which translate to the outB and inB, which will do the actual port accesses. Interrupts. How many recognize this picture? All right, excellent. How about 8, 9, 10 or so? So this is the legacy pick programmable interrupt controller. The way interrupts works in the beginning, single CPU systems. I guess all the way back to 8088, the original PC. There were 15 usable interrupt signals, interrupt inputs to these two interrupt controllers that are connected together. And the chain of events is, as described here, a device. Well, typically, each device would, one device would connect to each of these inputs, 0 through 15. The device wants attention from the CPU because something has happened. Maybe there's a byte coming in from the modem or from the keyboard, or maybe it's possible now to send a byte out to the modem or to the keyboard or wherever. A network card for that matter. So the device signals an interrupt, pulls one of these strings. The pick notices this, the interrupt controller, and it will, if it's one of these high ones, it's going to trickle through to the master. And the only interrupt signal going to the CPU is the actual int, that one. Yeah, so the one interrupt signal from the master pick is all that is going to the CPU. The CPU only accepts one single interrupt signal. But what about all these devices? How does that work out? Well, so when there's an interrupt, the CPU will acknowledge that it received this interrupt signal by pulling on this int A signal to the interrupt controller. And then it's going to wiggle the interrupt acknowledge signal a little bit more. Which causes then the program interrupt controller to write an address for the interrupt handler or the interrupt vector to the data bus. So the CPU says, okay, I got the interrupt. The CPU says, okay, what should I do now? The interrupt controller has been programmed, hence programmable interrupt controller, has been programmed to know that interrupt this and that, should be handled by code running at this particular address in memory. So the CPU says, okay, what should I do now? The programmable interrupt controller replies, you should go to this address in memory where the interrupt handler lives. So it writes that out to the data bus. The CPU reads the address and jumps to the address. And there's an interrupt handler running in the CPUs. So this was just one CPU. Then there's only one interrupt signal, even though we can have many interrupt sources. Hopefully this explains all the interrupt problems that were with the old ESA cards a little bit. Okay, what about when there are multiple CPUs? Then it gets fun again. There's always one bootstrap processor. That's the first processor that comes up running when the system is starting. That is all arranged in hardware, which processor will be running when the power comes on. Then any other CPUs are going to be application processors. So there's always only one running in the beginning and it has to, well, actually that's not true. That depends on if it's AMD or Intel. I think one of them, everyone comes up running and they have to agree to stop if they're not the BSP. But there has already been a decision made in hardware so that there's only one which is designated the BSP. It should check if it's the BSP and everyone should stop and the BSP will continue. Anyway, inside of these CPUs there's a local APIC. APIC is, I guess, advanced, programmable interrupt controller. The local APICs, there's one in each CPU, as I said, they communicate with each other. This, for example, have a transport or it could be some front side bus or such, system bus, whatever. They also connect with this IO APIC, which is the one dealing with... Well, this looks familiar. This is the same legacy APIC arrangement, which is still there even if you have an APIC. It might not be used. So the APIC situation, it needs to be configured before it's being used and if it's not configured then the system is still going to be using this legacy APIC setup. But if you configure the full-on APIC situation then you get the local APICs talking to each other and talking to the IO APIC and you can do really flexible mapping of all the interrupts coming into the IO APIC and all of the interrupts that can be generated by the local APICs also because by the time we have multiple CPUs the CPUs also have a lot of more functionality included than maybe the older ones did. So for example we have dimension already, machine check exceptions, MCEs. If the CPU detects that it has broken it can trigger an APIC interrupt and that can call into an interrupt vector somewhere. So the interrupt vectoring part is still the same. The local APIC will make sure that the CPU runs those often run some configured interrupt handler. The difference is that the difference from the legacy APIC situation is that well first of all the IO stuff which is connected to all the peripherals and the PCI bus down here that's separated out and the local APICs they also they have support for I think 256 interrupt sources instead of the 15 so there's plenty of interrupt signals available. They can come from interrupts can come from as I mentioned from within the APIC itself from within the CPU itself the APIC has also a timer which can generate interrupts and yes, of course the APIC enabled there it has to be enabled as I mentioned. Here's also the system management interrupt signal which goes into the CPU and not the APIC in this drawing. It's not more complicated but basically still the same principle you have programmed the APIC the interrupt controller with all the interrupt vectors and when the interrupt happens it will send the CPU to run the code that it should but there are a lot of possibilities with many different interrupts here. I think Rudolph will also come back to this. For RAM initialization how are we doing on time? For RAM initialization, what do we have to do there? Well, our goal in RAM initialization is to configure this thick red connection over here. It could be DDR2, it could be DDR3 in any case it's a lot of work we need to know exactly what kind of RAM is connected here on this side and the same for all of the CPUs or memory controllers which have RAM connected. Since this communication link isn't working what do we do? We then have to use this SM bus so from the CPU when we're doing a memory configuration we go through the North Bridge, South Bridge out onto the SM bus and follow this green line and talk to this little green guy which is an E-square prom on each DIMM. So a small serial E-prom it stores a couple of parameters. What size is this memory? How fast is it? Is it registered? Is it not registered? All the parameters, the timing supported by this memory module all the stuff that is needed to configure the memory controller correctly. And I'm not going to go into great detail with a memory controller configuration because it's so complicated. But I'm going to say that DDR2 at least requires some brute force searching for finding the correct tuning of the timing between the memory controller and the actual DIMM. So the firmware has to search through all possible settings or many possible settings for the tuning parameters in order to find the one that is working really well. And worst case, that parameter could actually change with the temperature in the room depending on how the board is laid out the traces on the main board. So it's a lot of work. Cache's RAM is used in core boot. This RAM initialization stuff. So when the RAM initialization is running, there is no RAM available. That means it's not possible to run C code because C compilers, they assume that there is RAM available. And RAM is used for the stack, which is used to call functions. So we can't use C code when we're doing this RAM initialization. And back when memory technology was simpler, or the memory buses were simpler, it was kind of okay to do I guess the memory initialization, the RAM initialization in assembly. We could do it in assembly language. And it wasn't all that bad. It wasn't too long. It was okay. But with this, for example, with this brute force search stuff that is in DDR2, it's really not something that we want to do in assembly anymore. So one way around it is to use cache as RAM. Which means that part of the CPU cache is used as memory. And in fact, it is memory. It's really fast memory. But normally it isn't addressable. But there's a way. It's documented by Intel even. It doesn't exactly... They don't exactly describe why you would do it. I guess... Well, they say how you do it, but not exactly that the result is cache as RAM. That you can run stuff without having RAM. You have to read between the lines a bit. But the information is there. You set up caching, and then you make sure that you load all the code that you want to run into the cache. And then you make sure that you don't run anything else. And that you don't access any code outside that. And if you do that, it's possible to have c code running without any RAM active. So that's used by Coreboots for many mainboards. But not for all yet. Our ambition is to have this for every mainboard. We have the cache as RAM support for a lot of different CPUs and platforms for AMD64 and for GeoLX and I think also for the VSC7. But all the boards aren't really using it yet. It can be tricky to do this in a general manner. We want cache as RAM support for everything, of course. But different platforms, different systems, they have restrictions on how big areas you can use for cache as RAM and where they need to live in which addresses you can use for this. So it's not really easy to do this cache as RAM setup always. Another option. So that's GCC. If you have cache as RAM you can use GCC compiled code. GCC assumes that there's memory. But before we started using cache as RAM we had another thing, another solution. ROM CC was created by one of the core boot developers. It's a C compiler custom made, one big source file that's really long. It generates machine code which doesn't need any RAM. Of course the X86 is sort of limited when it comes to the number of registers it has. So the C code cannot be infinitely complex because every time you call a function the C compiler has to reserve one register. So eventually you run out of registers and then the compiler will complain and is not going to be able to compile the source code you have. But if you have simple source code and if you write it in a certain way in lines for example can help then ROM CC does a fairly good job. There are a few bugs in there which have been a bit difficult to track down but I think the ROM CC code is pretty good by now. Question? So the question is how does ROM CC go at compile time when it runs out of storage? Yes. Well it has a model of the CPU that it's going to run on and at compile time it fills up that model it fills up the registers and eventually if it runs out of registers and it's impossible for the compiler to store the previous location then it's going to fail. Then you can do that function call at level 8 or 9. The compiler knows about the CPU but he probably doesn't know about the self-modifying dynamic code on the front end. The compiler surely knows about the CPU on the depth level he can cope with but he cannot know about somebody creating artificial calls and then... Artificial calls? If you get dynamic calls do you generate these types of... No dynamic calls? I think function pointers are much more... Yeah, for some... It could be supported as long as there's a register free but then you have to handle it on your order. Well it would be it would require one extra register I guess for saving the return or saving the function pointer somewhere. I think it's offline. Yeah, yeah. Sure explanation for this basically every function called is inlined around CC so if you have there is a function which calls itself around CC will try to inline and eventually detect that you have an infinite loop or something like that so recursion or something like that function pointers forget it so if you're fully inlined assembly code with no calls at all it can't be compiled by around CC that's the dream. So I hope that basically working out to be unrolled. Yeah, right it unrolls the source code completely, right? I think it should be possible to implement function pointers though but it might not be in the kernel code. Okay, all right. Still ROM CC is even though we're moving away from ROM CC code it's I think it's still useful for example serialize I believe is the ROM shell for serialize is compiled with ROM CC and it's really an amazing effort that went into it. Execution modes in the x86 there's a good old real mode the classic execution mode that every modern CPU still starts up in. You have a bunch of 16-bit registers the ones up there I hope I don't forget one. The first four are segment registers and the rest are they have sort of intended purposes but you can mix and match almost freely not quite but you can mix and match a bit and every memory address as I said in real mode is 20 bits so two of these 16-bit registers need to be combined and I've always seen that being called segmented addressing and it's written in the form segment register colon offset register they're both 16 bits and the address ends up being the segment register shifted left by four or multiplied by 16 and then add on the offset register. So for an example if ds equals f 00 0 hexadecimal and si equals 6 00 0 hexadecimal then the ds si segmented address would be a physical address of f 6 00 so that way you can reach a full megabyte of address space and this was in 8086 8088, 186 and 286 and then with the 386 there was the protected mode there was one protected mode in the 286 as well but it was so different that I'm not going to bother I don't remember even all the details but the protected mode as we know it and usually call it is the one that came in 386 it has a concept of privilege levels where you can specify that some parts of code is allowed to do some things and not some other things and this is also what every modern operating system relies on in order to do security properly otherwise you wouldn't be able to do anything even as a user in Linux for example but only the root user is really allowed or the kernel is really allowed to do anything in the system when one of these privilege instructions or when you're trying to do if you're trying to do something that you're not allowed to do then the 386 or a protected mode CPU is going to throw an exception and this can be handled by an interrupt handler and then the APIC stuff comes into play and you end up running some other piece of software which can sort of detect what happened and then it goes all the way back and tells the user that oops you did something that you're not supposed to do instead of crashing or whatever also included in the protected mode which is really engaging this is a reference table or a lookup table for addresses so you're using an address but it's not like up here if you say you want this address it might actually be a completely different address so there's there's a translation layer in between the address you're using the virtual address and the address that is actually seen the protected mode not actually protected mode this is more than 386 the 386 added 32 bit registers so there are versions of all the ones from AX out to SP that are 32 bits the lower 16 bit are the same and some of those can be divided into 8 bit registers and then the segment registers they change into what is called selectors it's the same register name it just has a different function in protected mode the selector will look up a data structure which has information about paging and privileged instructions and also base and limit so this is all part of the translation depending on what you put in cs if you say put for example 0 then you're going to get the first entry in this lookup table of selectors or descriptors and that means if you address if you access address 0 it's actually going to be somewhere completely different but if you then change cs to be 8 instead and you move one step forward in this table the global descriptor table as they're called and then if you're accessing 0 it gets a completely different meaning the limit specifies how big memory block you can access starting from the base address so system management mode I mentioned it's triggered by system management interrupt when the processor enters system management mode it's always running in real mode the switch to protect the mode if it wants to interrupts are always disabled and the debug traps are always disabled so when you're running in system management mode you're really you're really isolated the machine is all yours system management mode can be entered by as I mentioned IO traps or even MMIO traps so the memory maps register accesses machine check exceptions and APIC anything in the APIC can also generate or result in system management mode execution embedded controllers I'm out of time so unfortunately no rant about embedded controllers it's the 851 in the Super IO it can do a whole lot of stuff which sort of messes up the system because it's transparent and it might also be very difficult to detect but yeah, no thanks to Luke and questions if there's time how does Ron CC store local variables and variables pass to fantasy? in registers so you can have only a few local variables in the Super IO 3 851 when does it get it's go from good question so it depends on sometimes the 851 there it can be a standalone chip and if it's a standalone chip it can have built in firmware but it could also be sharing with the main sharing the boot flash with the main firmware in the system so say the first the first 50 56 kilobytes is the firmware for the microcontroller the embedded controller fairly common or it can have it's own flash chip it can definitely have it's own flash chip as well question system management mode yes yes yes definitely yes and someone also earlier asked the question where the system management code that is run in coreboot where does it come from it is also in coreboot we have two separate implementations of system management code handlers one is from AMD that's the one for the Geo.LX but they open sourced that and then there's the code for Intel and I think well maybe Rudolf you also wrote some small system management code for the AMD64 but it's all included in the coreboot source and there's full control and it does really very little because it wants to get out of the way all right okay thank you very much