Foreword

These days hardware is hidden beneath a thick blanket of Operating System's code. Yet, for me and many other folks, according to Google searches, a possibility to reach and experiment with hardware would be a very exciting opportunity. I have created an exploratory platform consisting of two Intel-based computers connected via RS232 interface. One computer, the Master, is running Windows and is used to control the second computer. The second one, the NakedCPU, runs essentially without any operating system, hence it is available to truly low-level experiments. My platform was featured on the cover of Circuit Cellar Magazine, issues 259, 260. Current article is an adaptation of the original publication, which is available on my web site.

Introduction

It seems that experimentation with a PC is limited to developing high-level code software with the aid of numerous libraries and technologies hiding the hardware beneath layers and layers of code. Rarely limited experimentation with PC hardware is possible, however one has to install drivers allowing some access to hardware, because OS naturally does not permit us to do any low-level activities. The sad part is that such drivers are mysterious themselves. It is safe to say that the hardware programming was well known to many computer professionals and enthusiasts in the 80-s. Later the people forgot about it, while the technology has tremendously leaped ahead. In this article, I try to bridge the gap in time and to revive the interest in hardware programming based on the state of the art technologies and concepts. There is a Russian saying: "Everything new is actually well-forgotten old".

This article is a result of my interest in the Intel CPU, chipset, I/O controller and other essential PC devices from the perspective of low-level hardware programming unobscured by an operating system and drivers. The motivation for this project was to reach out to people with inquisitive minds who would appreciate a possibility to directly experiment with the CPU, chipset and other hardware. Here I present NakedCPU: a facility providing full access to hardware and CPU without any restrictions imposed by the operating system. Importantly, the processor will not be obscured by Linux, DOS or Windows, and it will be operating in its most interesting and powerful regime - the protected mode. In the text, the users are referred as inquirers, because NakedCPU is made for researchers, i.e. devoted geeks, rather than regular users.

The other goal of this article is to provide the inquirers with a roadmap into navigating hardware documentation, which is confusing and difficult to find otherwise. I did not want to retell the documentation, because many computer concepts and technologies quickly become obsolete. With the roadmap, however, it will be easier to follow the newer technologies and documentation.

Interesting Facts

Let us think for a moment about one of the modern Intel CPU varieties, for instance Intel Core 2 Duo. Impressively, this processor is capable of consuming up to 75A of current [1]! Also, it is not a simple processor: its documentation consists of 5 volumes with the total page count of approx 4200 pages [2]. Intel CPU does not operate alone: it is interfacing a chipset, i.e. a Graphics and Memory Controller Hub (GMCH). The chipset on the other side is connected to an I/O Controller Hub (ICH). Interestingly, this arrangement is analogous to our nervous system with brain, brain stem and a spinal cord. GMCH and ICH are processors themselves, containing hundreds of configuration and control registers. The documentation on GMCH and ICH spans over 1400 pages [3, 4]. No wonder why operating systems hide actual hardware under a thick blanket of intermediate code!

Working Principle of the NakedCPU

NakedCPU is an experimental platform exposing the hardware internals of a PC. Experimentation with NakedCPU requires two computers (Figure 1). One is the master computer having Windows and Visual Studio software, whose job is interacting with us and the second computer. The second computer, i.e. the NakedCPU, is connected to the master via RS232 interface.The NakedCPU computer is booted up with a small startup code (provided here), which enables it to communicate via RS232 with the master. Upon startup, the NakedCPU is expecting two separate packages of bytes: one is a stream of Intel CPU opcodes to be executed (i.e. the executable) and the other one is the data to be processed. The executable can modify any part of memory, chipset registers, etc, and even overwrite the startup code. In other words, the freedom is yours.

Starting up NakedCPU

NakedCPU will not be alive without some sort of a startup code. At startup we have to accomplish two tasks: switch the CPU into the Protected Mode and begin listening on the serial port for two packets of bytes: executable and data. In order to supply NakedCPU with a startup code, the easiest way is to prepare a bootable floppy disk with our own code. Certainly, one can also put this code into a hard drive. The startup code (up to 512 bytes) is written in assembly language and must be stored in the sector 0, i.e. the Master Boot Record (MBR) of the disk. It is difficult to use assembly language compilers and linkers such as MASM, since they tailor the executable to a particular OS. There is, however, a binary editor HexIt [5], which among other things allows direct conversion of assembly commands into binary code. Using this editor, a binary file of the future MBR was created. The content of this file can be seen in Appendix. "Anatomy of MBR" provides detailed dissection of the content. A small utility "Firstsectwrite.exe", see Appendix, was written to transfer this file into sector 0 of the disk. Although the code of this utility is quite simple, it deserves some attention. A Windows API call

CreateFile(TEXT( " \\\\.\\A:" )...)

opens raw communication with a disk, in this case a floppy drive A, to allow writes into the sector 0. It is important to note, that this call will be only successful under the administrator account. In this paper, a Dell Optiplex 760 computer was used to conduct the experiments. It had a floppy drive attached via USB and BIOS startup options allowed to boot up the computer from such a drive.

In this paper, a Dell Optiplex 760 computer was used to conduct the experiments. It had a floppy drive attached via USB and BIOS startup options allowed to boot up the computer from such a drive.

NakedOS

It may sound contradictive to the spirit of the article to be OS-free, however NakedCPU is booted up with a tiny (262 bytes long) 32-bit "operating system", NakedOS, which makes the NakedCPU capable of communicating with the outer world via serial port. In fact, we did not compromise our principles of truly free exploration, because NakedOS is absolutely transparent and its code completely presented in the Appendix. NakedOS defines several memory segments (Table 1), which are useful as initial environment for the inquirer's executable. Intel documentation [2] provides explanation for protected mode memory segments, Global Descriptor Table (GDT) and Interrupt Descriptor Table (IDT). In addition, NakedOS defines two software interrupts and a base vector for hardware interrupts. Note: the INT interrupts have nothing to do with DOS or BIOS; they are solely defined by our code.

Segment Base Size Descriptors, type Extended memory 0x100000 ~ 128Mb 0x28, data Screen, character mode 0x0B8000 4Kb 0x20, data Target executable 0x93B 64Kb 0x30, code 32;0x38, data NakedOS 0x800 315 bytes 0x10, code 32 Stack 0x400 1024 bytes 0x18, stack 32 System data

IDT: 0x3FF-0x200

GDT: 0x1FF-0 0x0 1024 bytes 0x8, data

Interrupts Info INT 0x20 Read a packet from serial port; destination ES:[EDI]; mandatory condition DS=ES. First 4 bytes of the packet indicate in bytes the length of the subsequent string. Upon return, ECX contains the number of bytes received. INT 0x21 Send to serial port a string of ECX bytes, located at DS:[ESI]. IRQ0 Hardware interrupts base vector is 0x28.

Immediately after start, NakedOS is expecting two transactions: one for the executable code and another for data. Each transaction is a stream of bytes sent over the RS232 (see Figure 2). The first transaction is written into the memory segment "Target executable", while the second transaction goes into the "Extended memory" segment. After completion of the second transaction, NakedOS transfers control to the executable by a long jump:

jmp 00030:000000000

From that moment, in principle, any memory occupied by NakedOS can be overwritten by activities of the inquirer's executable. The hardware interrupts are normally masked when NakedOS is running; however the 8259 interrupt controller is set up (see additional file MBRListingNakedOS.doc in the download archive) to handle the interrupts if the inquirer decides to unmask them. Detailed instructions on programming the interrupt controller are provided in the documentation for the I/O Controller Hub (ICH) [4].

NakedCPU Explorer and OtherExecutables

The important issue remains how to send an executable code to NakedCPU to conduct experiments. Recall the beginning of the article, where it says that two computers are involved. The master has a Visual C++ project, NakedCPU Explorer, which acts as a "shell" allowing inspection and modification of chipset registers and memory. The code defines a class having a constructor, which provides __asm{} brackets to be filled up by the inquirer with executable code:

class Ports : public NakedCPUcode { public : Ports() { DWORD pe, ps; __asm { mov pe, offset end mov ps, offset start jmp end start: mov ax , 0x28 mov es , ax mov ds , ax mov ax , 0x18 mov ss , ax mov esp , 0x3fe xor edi , edi mov eax , 'OLEH' stosd xor esi , esi mov ecx , 4 INT 0x21 ... _emit 0xEA _emit 0x00 _emit 0x00 _emit 0x00 _emit 0x00 _emit 0x10 _emit 0x00 end: nop } if (!PrepareCode(ps, pe)) delete this ; } };

Since Microsoft Visual C++ is running on the master PC having an Intel CPU, the compiler will translate the assembly code into appropriate opcodes, which are naturally suitable for the NakedCPU! Specifically, this class is derived from another class, NakedCPUcode, which performs a preparatory work by extracting the opcodes produced from the code in the __asm{} brackets and making them available for sending over to the NakedCPU. Note, NakedCPU only receives the code between "start" and "end" labels. It is important to understand that the master computer will not execute the code in the __asm{} brackets, it simply jumps over it. The strange keyword "_emit" allows placing opcodes directly by their hexadecimal values - for some reason a long jump is not permitted when using Visual Studio compiler.

Any other executable code, besides the NakedCPU Explorer, can be prepared and sent to the NakedCPU computer. Actual sending of the NakedCPU Explorer code is accomplished the following way:

Ports ncd; SerialComm Com1; if (!ncd.UploadEx(&Com1)) throw 1 ;

The project also defines a class SerialComm and a function SendNakedCPUdataRecvResponse to send and receive data. It is worthwhile to examine the straightforward code of the project to understand the details of communication with NakedCPU. Besides serving as an example, NakedCPU Explorer sends an executable to NakedCPU, which permits interactive examination and modification of various chipset and I/O controller registers. NakedCPU Explorer offers eight commands "write", "write32", "read", "read32", "pci", "memread", "memwrite" and "quit". First four commands will ask for a port address, i.e. an address in the CPU I/O space. With these commands, NakedCPU will write to and read from a GMCH or ICH register, one or four bytes. The fifth command will ask for Bus (decimal), Device (decimal), Function (decimal) and Register (hexadecimal) values. The values will be packed into the port 0xCF8 to open a "window" into the PCI configuration space, accessible via port 0xCFC. Details on addressing PCI devices are provided in the chipset documentation [3]. Memread and memwrite allow reading and writing double words from and to the memory respectively.

Note: NakedCPU Explorer does not use any hidden "helper" drivers or libraries. The code is small and entirely transparent for the inquirer's perusal.

Experiments

The following sections describe experiments with direct access to the hardware and CPU.

Making noise

Although it may sound trivial, making a PC speaker to produce sound involves understanding of timers and some low-level work. Ironically, there seems to be no way to make a speaker beep using Windows API on Vista and XP 64-bit version, because Microsoft decided that the speaker hardware is obsolete [7]. Certainly, in the past, the DOS programmers must have known how to do it, but now it seems to be forgotten. Reading ICH documentation [4] and conducting a few experiments resulted in the following protocol:

>write

Port address: 0x61

Value: 0x3

Speaker enabled. NakedCPU begins producing a continuous sound. >write

Port address: 0x43

Value: 0xbe

>write

Port address: 0x42

Value: 0x10

>write

Port address: 0x42

Value: 0x1

Change the default frequency by writing a timer configuration word. Sound stops, because timer is expecting to receive a two-byte divisor. Write a new value 0x0110 in two transactions, after which NakedCPU will begin producing a high-pitch noise. >write

Port address: 0x42

Value: 0x0

>write

Port address: 0x42

Value: 0x20

Write a larger divisor 0x2000 to lower the frequency. Writing the configuration word is not necessary.

Lighting an LED

Parallel port is becoming more and more obsolete, nevertheless it offers a possibility to read and send data over 8 lines. Strangely, ICH documentation does not say anything about programming a parallel port. Browsing Internet reveals that there is still some interest with regard to the parallel port and programming information is available. Connect an LED to the D2 port line via 470 Ohm resistor and follow the protocol below, which demonstrating writing to and reading from the parallel port.

>write

Port address: 0x77A

Value: 0x34

>write

Port address: 0x378

Value: 0x4

Parallel port turns into Extended Capabilities Port mode via modification of the Extended Control Register (0x77A). Line D2, goes HIGH and LED glows. >write

Port address: 0x77A

Value: 0x34

>write

Port address: 0x37A

Value: 0x2c

Reading from LPT is also possible. By writing 0x2c into the Port Control Register (0x37A), we make parallel port read. The LED slightly glows indicating that pull up resistors are enabled in the reading mode.

The "first cry"

Which instruction the processor executes first after power on? Documentation [2] says that the processor reads its first instruction from the address 0xFFFFFFF0, i.e. 16 bytes below 4GB. Attempting to examine this address with a debugger is fruitless (tested, did not work). In order to reach this high address, which is in the range of high BIOS, a small executable for the NakedCPU was prepared. The executable defined a segment of memory addressing high BIOS and sent the content of the 16 bytes below 4GB back to the master computer. Quite expected, there was a short jump, approximately to 30KB below. The executable was modified to download the entire chunk of memory 30KB below 4GB up to the top. Especially curious inquirers are welcome to investigate the content, which was saved and available for download. As a general impression, one can see many accesses to PCI bus and calls for CPUID instruction. It certainly makes sense, because various devices have to be set up and BIOS is attempting to determine which processor is being used.

Network

Communication via network is accomplished using the Media Access Controller (MAC). Documentation is available at the Intel web pages. It is also helpful to read first three chapters of the IEEE 802.3-2008 standard to get an idea of the low-level network lingo as well as the packet format sent over the wires [8].

Once again we will use NakedCPU Explorer to investigate the internals of the Media Access Controller and conduct some experiments. MAC requires data structures in memory and configuration transactions via I/O address space. First, we must determine I/O address of MAC, which is called Base Address 2 (BAR2). The address is stored in the PCI configuration space at bus 0, device 25, function 0 (B0:D25:F0) register 0x18. By the way, there is a confusion in the documentation referring to the same register. ICH calls this particular register as MBARC [4], while MAC documentation [6] calls it BAR2. Conduct PCI transactions with NakedCPU Explorer as follows:

>pci

Enter Bus Device Function 0xRegister: 0 25 0 0x18

>read32

Port address: 0xcfc

ecc1

PCI transaction consists of two steps: define the location and read the content.

The number 0xECC1 means that the I/O address is actually 0xECC0 with the 0th bit hardcoded to 1 to indicate that the address is indeed in the I/O space as opposed to being memory-mapped [6]. The latter indication is important because all configuration and communication with MAC can also be done using memory-mapped registers, which is faster, however for our experiments it is sufficient to use the I/O space, because it is simpler and accomplishes same results as with memory-mapped operations.

In order to interact with MAC, the inquirer writes an address of a register within MAC into the BAR2 I/O address (0xECC0). After that, BAR2+0x4 (0xECC4) becomes a window to the value of that MAC register. It is important to mention that BAR2 and BAR2+0x4 accept only 32-bit double word read / write operations. MAC registers have plenty of bits to deal with and some bits are dependent on one another. It is very difficult understand the settings just by looking at the hexadecimal value of a register. An Excel worksheet InterpretRegister.xls (available for download) features a macro that greatly helps in this situation. Specifically, a table containing bit descriptions should be copy-pasted from the documentation PDF and a hexadecimal value of a register will be converted into binary 1s and 0s in appropriate cells right next to the description text, see Figure 4.

Let us examine control CTRL(0x0) and status STATUS(0x8) registers; the address of the register is given in parentheses. After power on with network cable unplugged:

>write32

Port address: 0xecc0

Value: 0

>read32

Port address: 0xecc4

100240

This particular bit constellation determines among other things enabled automatic configuration for speed and full/half duplex.

>write32

Port address: 0xecc0

Value: 0x8

>read32

Port address: 0xecc4

80080600

These bits tell that there is no link established but initialization is completed.

After connecting the master computer with the NakedCPU, CTRL register stays the same as expected, while the status register changes to 0x80080683. The new value means full duplex communication, established link and 1Gbps speed. The master computer running Windows XP reported the same communication parameters, which indicates that the NakedCPU network interface was able to negotiate with the master computer's interface on the hardware level.

Receiving and interpreting network packets

In this section, we will experiment with reading network packets originated from the master computer. It was found that when master computer detected live NakedCPU via the network cable, Windows began generating DHCP requests. These requests are attempts to obtain an IP address and other high-level network settings, because Windows assumes (erroneously) that the NakedCPU is a router or a network server. Although Windows is mistaken, this is perfectly fine for our experiments, because we can catch these packets and examine them.

MAC uses direct memory access to store the received data. We have to create several descriptors, which will tell MAC where to write the data. Thus, two memory ranges are required: one for the descriptors and the other for packets. Referring to Table 1, one can see that there is an area of memory above the address 0x100000 available for inquirer's data. Bearing in mind that NakedCPU Explorer uses a tiny bit of that memory to store incoming commands, we can safely use addresses above 0x100500. It is sufficient to create two descriptors for the initial experiments. A descriptor is a data structure of four double words (16 bytes). The first two double words are 64-bit physical address of the location where the packet is to be stored. With the ability of the NakedCPU Explorer to write into memory locations, let us create the descriptors at the address 0x100500, pointing to two 512-byte long buffers located at the addresses 0x101000 and 0x101200. A collection of descriptors is called "queue". After MAC finishes with storing packets, it will update the descriptors to indicate received packet size, errors and several other parameters.

>memwrite

0xAddress above 0x100000: 0x100500

Num dwords: 8

0x101000

0

0

0

0x101200

0

0

0

The command "memwrite" asks for the address and the number of double words to be written. Note, writing below 0x100000 will cause general protection fault and reboot of the NakedCPU.

MAC has to know the location of the descriptors, the size of the receive buffers and the type of packets to receive. This information has to be stored in several MAC registers. RDBAL0(0x2800) and RDBAH0(0x2804) - low and high portions respectively of a 64-bit physical address of the base of the queue. RDLEN0(0x2808) - length of the memory buffer allocated for the queue. RDH0(0x2810) and RDT0(0x2818) - head and tail pointers respectively. RFCTL(0x5008) - receive filter control register. RXCSUM(0x5000) - receive checksum control register. Before setting up these registers, a bit 26 of the CTRL(0) register has to be set to 1, which will cause MAC reset. After setting up all registers, data reception is initiated by writing into RCTL(0x100) to set up the "enable" bit, the size or the receive buffers reception mode and type of the descriptors.

For the CTRL, RCTL, RFCTL and RXCSUM registers, the worksheet InterpretRegister.xls shows values (and bit states) that are going to be used in our experiments. The meaning of value for the RDLEN is somewhat confusing. According to the documentation, the length of the queue buffer must be a multiple of 128, which means at least eight descriptors (128 / 16) must be in the queue. We have only two descriptors, however. I have determined experimentally that it is not a problem to tell MAC that the queue buffer is larger than it needs to be, as long as the RDT0 register is pointing to the end of the actual queue. Hence, for our particular experiment we must set RDLEN = 0x80, RDT0 = 0x2.

Before receiving the packet by NakedCPU, the Master computer should not be sending DHCP packets. To suppress the DHCP packets originating from the Master computer, the following should be entered in the Windows command-line tool under the Administrator account:

ipconfig /release

Next, copy and paste columns of the Table 2 into the NakedCPU Explorer in the order I - V. Note that at the end of the 4th step, MAC is ready for enabling reception. That step ends up in reading from the status register, which should result in a value 0x80683. This value is similar to the one previously described (0x80080683, page 8) with the difference that the bit 31 is cleared, which indicates that the DMA clock cannot be lowered to Â¼ of its value. The reason why MAC changed its "mind" concerning the DMA clock is not known, but this is not relevant for our experiments.

I II III IV V write32

0xecc0

0

write32

0xecc4

0x4100240

write32

0xecc0

0x2800

write32

0xecc4

0x100500



write32

0xecc0

0x2804

write32

0xecc4

0

write32

0xecc0

0x2808

write32

0xecc4

0x80



write32

0xecc0

0x2810

write32

0xecc4

0

write32

0xecc0

0x2818

write32

0xecc4

0x2



write32

0xecc0

0x5008

write32

0xecc4

0x8000

write32

0xecc0

0x8

read32

0xecc4





write32

0xecc0

0x100

write32

0xecc4

0x402800A















To initiate the Master sending packets, type the following in the command-line window under the Administrator account:

ipconfig /renew

After reading from the network, MAC updates the two descriptors. With the memread command observe the new values by reading 8 double words beginning from the address 0x100500. You will see that the descriptor's address field is changed and two additional values appeared. Figure 5 shows the new values that my computer produced. Detailed information about the fields is provided in the MAC documentation [6]. Briefly, the lengths of the packets are 342 bytes (0x156); no errors occurred, the descriptors are indicated as "done" and the entire packet was able fit to the buffer (0x20073).

Descriptor 1 Descriptor 2 0

0

f8270fe8

f8270fe9

20073

20073

156

156



MAC stored the actual two packets at the addresses 0x101000 and 0x101200 respectively; their contents are present in InterpretRegister.xls, "Packets" worksheet. Figure 6 shows the beginning of the stored data array and the order of transmission. The first six bytes marked red are the destination (broadcast) address, which are followed by the source addresses and the two-byte length / type field. The latter field is transmitted with most significant byte first [8], which makes it to be 0x0800. If the value of the length / type field is less or equal to 0x05DC, then it indicates the length of the packet, otherwise its type (Ethertype). Web pages at standards.ieee.org in theory provide specific Ethertype values, however it is virtually impossible to find the actual list of values. Luckily, Wikipedia points to an exact URL in the innards of the ieee.org site [9]. According to the standard, Internet Protocol (IP) is designated with the Ethertype 0x0800. Apparently, next step is to investigate the format of the Internet Protocol, which is described in RFC894, which points to RFC791 [10].

The fields of the IP header are transmitted in a similar way as the previously described length / type field, i.e. most significant bit and the most significant byte first. In contrast to the intuitive notation, where bit 0 is the least significant bit, RFC791 provides the opposite, with bit 0 to be the most significant bit. Table 3 shows continuation of the received packet and the assignment of its specific values to the fields of the first 32-bits of the IP header. Important fields are IHL and Total Length. IHL indicates the number of 32-bit words in the header. In our case it is 5, which means that according to RFC791 Options and Padding fields are omitted. It is interesting to note that MAC reported receiving 342 bytes and the IP header indicated 328 (0x0148) bytes. The difference of 14 bytes makes perfect sense, because they make up to two bytes of the length / type field plus 2*6 bytes of destination and source hardware addresses.

All other fields of the IP header are easy to map following this example. Specifically, the field values are: Identification - 0x0fe8 (packet 1), 0x0fe9 (packet 2); Flags and Fragment Offset - 0; Time to Live - 0x80; protocol - 0x11; Header Checksum - 0x29be (packet 1), 0x29bd (packet 2); Source IP address - 0.0.0.0; Destination IP address - 255.255.255.255. It is understandable, that the master PC is asking for an IP address while doing the dynamic host configuration process, therefore the source IP address is all zeroes. For the destination, the address is all 255.255.255.255, which is a broadcast address, similar to the hardware broadcast address (6 bytes, all 255).

Bit: 0 - 3 4-7 8-15 16-31 ...

00450008

E80F4801

...

Version

0x4

Internet header length (IHL)

0x5

Type of Service

00

Total Length

0x0148



The value for the protocol field is 0x11 (17); according to RFC790 it refers to the User Datagram protocol (UDP) - the next level of data encapsulation - which is described in RFC768. According to that document, a UDP header contains four 16-bit words. In the order of transmission, these words are source port, destination port, length and checksum. The values received by NakedCPU in my experiment were source port - 0x0044, destination port - 0x0043, length - 0x0134, checksum - 0x5c1a (packet 1) and 0x581a (packet 2). The length of 308 (0x134) bytes makes sense, since IP header reported the total datagram length of 328 bytes minus 20 bytes occupied by the IP header. The source and destination port numbers should have been explained in RFC790, however it turned out that a long chain of other documents obsolete this one. At the end of the chain, it is suggested to look at the website of the Internet Assigned Numbers Authority (IANA), where, unfortunately, the information is not well organized. It was possible, however to find among the obsolete RFCs that port numbers 67 (0x43) and 68 (0x44) correspond to the Bootstrap Protocol, server and client ports respectively. The Bootstrap Protocol is described in RFC1542 that points out to the DHCP protocol, see RFC2131. A summary of all fields discussed in this section is provided in Figure 7.

Conclusions and Future Outlook

It is possible to directly experiment with Intel CPU and other PC hardware without any layers of unknown intermediate code that is intended to make our life "easier". As of yet, the most comprehensive documentation exists for the processor itself [2]. The other hardware is not well documented, which is why it takes a significant amount of efforts to gather pieces of information from the Internet and conduct experiments directly. The old books that dealt with hardware are DOS oriented and seriously obsolete. The new hardware is hidden behind layers of unknown code.

In theory, the NakedCPU platform enables developers to create task-specific applications using only needed components. For instance, if we are talking about a large-scale database, there is no need to support GUI, USB plug and play, audio cards, .NET and many other things. An additional bonus to the NakedCPU platform is immunity to viruses. Like in biology, where flexible viruses attack well-evolved organisms, the computer viruses attack well developed operating systems. With the NakedCPU, on the other hand, a particular task-specific solution can be very unique; hence the virus-creators will simply have not enough information to explore potential security holes.

Original Publication

The original publication is available on my web site. Click the images:

References

Intel Core 2 Duo Processor E8000 and E7000 Series. Datasheet. June 2009. PDF Intel 64 and IA-32 Architectures Software Developer's Manual, all volumes combined PDF Intel 4 Series Chipset Family. Datasheet PDF Intel I/O Controller Hub 10 (ICH10) Family. Datasheet. PDF M Klasson. HexIt - The Hex Editor Here Intel I/O Controller Hub 8/9/10 and 82566/82567/82562V Software Developer's Manual. PDF MSDN, Beep function. Here IEEE Standard for Information technology - Telecommunications and information exchange between systems - Local and metropolitan area networks - Specific requirements. Part 3: Carrier Sense Multiple Access with Collision Detection (CSMA/CD) Access Method and Physical Layer Specifications. IEEE Std 802.3 -2008. Here A list of Ethertype values pointed by Wikipedia. Here All RFC documents are available at http://www.ietf.org/rfc/rfcZZZZ.txt, where ZZZZ is a four-position number of the document, prefixed with zeroes if necessary. Also here All RFCs

Appendix

Anatomy of MBR

Description MBR location Determining current address while the processor is still in real mode after power on. BIOS has loaded the MBR somewhere into the memory and transferred control to our code. The current address is necessary to locate physical address of the pseudodescriptor, which is in turn defining a physical address and a limit for the Global Descriptor Table (GDT). 0x3E - 0x4D LGDT instruction (Load GDT register) is loading pseudodescriptor, which is pointing to GDT. 0x52 GDT and Interrupt Descriptor Table (IDT) are copied into a new memory location, beginning from linear address 0x0. GDT and IDT are defining memory segments for the processor to operate in protected mode. 0x57 - 0x64 The MBR contains a very tiny 32-bit protected mode "operating system", let us name it NakedOS. 0x80 - 0x186 NakedOS is copied into a new memory location beginning with linear address 0x800. 0x65 - 0x71 Switching into protected mode is accomplished by adjusting the Machine Status Word using a LMSW instruction. 0x72 - 0x78 Transfer control to NakedOS. 0x7B Set up 8259 interrupt controller 0xF5 - 0x105 Transfer control to the inquirer's executable 0x106

Critical data structures

Structure MBR location Pseudo-descriptor IDT 0x194 Pseudo-descriptor GDT 0x1BA Null descriptor 0x1C0

MBR Listing: NakedOS

Address Opcode Mnemonic 00000000 EB3C jmp short 00000003E .............some remnants from FAT............................... 0000003E FA cli 0000003F 33C0 xor ax , ax 00000041 8ED0 mov ss , ax 00000043 BC007C mov sp ,07C00 00000046 16 push ss 00000047 07 pop es 00000048 0E push cs 00000049 1F pop ds 0000004A E80000 call 00000004D 0000004D 89E5 mov bp , sp 0000004F 8B5E00 mov bx ,[bp+000] 00000052 0F01976D01 lgdt q.[bx+0016D] 00000057 89DE mov si , bx 00000059 81C67301 add si , 0173 0000005D B94000 mov cx , 040 00000060 31FF xor di , di 00000062 FC cld 00000063 F3 repe 00000064 A4 movsb 00000065 BF0008 mov di , 0800 00000068 89DE mov si , bx 0000006A 83C633 add si , 033 0000006D B93B01 mov cx ,013B 00000070 F3 repe 00000071 A4 movsb 00000072 0F01E0 smsw ax 00000075 0D0100 or ax , 01 00000078 0F01F0 lmsw ax 0000007B EA00001000 jmp 00010:00000 -----from here 32-bit code segment ------------------------------ 00000080 66B81800 mov ax , 018 00000084 8ED0 mov ss , ax 00000086 BCFE030000 mov esp ,03FE 0000008B 66B80800 mov ax , 08 0000008F 8EC0 mov es , ax 00000091 E492 in al , 092 00000093 0C02 or al , 02 00000095 E692 out 092 , al 00000097 66BAFB03 mov dx ,03FB 0000009B B083 mov al , 083 0000009D EE out dx , al 0000009E 66BAF803 mov dx ,03F8 000000A2 66B80600 mov ax , 06 000000A6 66EF out dx , ax 000000A8 66BAFB03 mov dx ,03FB 000000AC B003 mov al , 03 000000AE EE out dx , al 000000AF 31C0 xor eax , eax 000000B1 BF00020000 mov edi , 0200 000000B6 B900020000 mov ecx , 0200 000000BB F3 repe 000000BC AA stosb 000000BD BF00030000 mov edi , 0300 000000C2 BE14010000 mov esi , 0114 000000C7 0E push cs 000000C8 1F pop ds 000000C9 0F011E lidt q.[ esi ] 000000CC 83C606 add esi , 06 000000CF B904000000 mov ecx , 04 000000D4 F3 repe 000000D5 A5 movsd 000000D6 66B83800 mov ax , 038 000000DA 8EC0 mov es , ax 000000DC 8ED8 mov ds , ax 000000DE 31FF xor edi , edi 000000E0 CD20 int 020 000000E2 66B82800 mov ax , 028 000000E6 8EC0 mov es , ax 000000E8 8ED8 mov ds , ax 000000EA 31FF xor edi , edi 000000EC CD20 int 020 000000EE 6631C0 xor ax , ax 000000F1 8EC0 mov es , ax 000000F3 8ED8 mov ds , ax 000000F5 66BA2000 mov dx , 020 000000F9 B011 mov al , 011 000000FB EE out dx , al 000000FC B028 mov al , 028 000000FE 42 inc edx 000000FF EE out dx , al 00000100 B004 mov al , 04 00000102 EE out dx , al 00000103 B001 mov al , 01 00000105 EE out dx , al 00000106 EA000000003000 jmp 00030:000000000 .............random bytes...................................... 00000140 66BAFD03 mov dx ,03FD 00000144 EC in al , dx 00000145 A801 test al , 01 00000147 74FB jz short 000000144 00000149 66BAF803 mov dx ,03F8 0000014D EC in al , dx 0000014E AA stosb 0000014F 50 push eax 00000150 66BAFD03 mov dx ,03FD 00000154 EC in al , dx 00000155 A820 test al , 020 00000157 74FB jz short 000000154 00000159 58 pop eax 0000015A 66BAF803 mov dx ,03F8 0000015E EE out dx , al 0000015F C3 ret 00000160 57 push edi 00000161 B904000000 mov ecx , 04 00000166 E8D5FFFFFF call 000000140 0000016B E2F9 loop 000000166 0000016D 5F pop edi 0000016E 8B0F mov ecx ,[ edi ] 00000170 85C9 test ecx , ecx 00000172 7409 jz short 00000017D 00000174 51 push ecx 00000175 E8C6FFFFFF call 000000140 0000017A E2F9 loop 000000175 0000017C 59 pop ecx 0000017D CF iretd 0000017E AC lodsb 0000017F E8CBFFFFFF call 00000014F 00000184 E2F8 loop 00000017E 00000186 CF iretd .............random bytes......................................... 00000194 FF01 00000196 0002 00000198 0000 0000019A E000 0000019C 1000 0000019E 008E0000 000001A2 FE00 000001A4 1000 000001A6 008E0000 000001AA 0000 000001AC 0000 000001AE 0000 000001B0 0000 000001B2 0000 000001B4 0000 000001B6 0000 000001B8 0000 000001BA FF01 000001BC 0000 000001BE 0000 000001C0 0000 000001C2 0000 000001C4 0000 000001C6 0000 000001C8 FF03 000001CA 0000 000001CC 00920000 000001D0 0A13 000001D2 0008 000001D4 009A4000 000001D8 FF03 000001DA 0004 000001DC 00924000 000001E0 FF0F 000001E2 00800B92 000001E6 0000 000001E8 007800 000001EB 0010 000001ED 92 000001EE 8000FF 000001F1 FF3B 000001F3 0900 000001F5 98 000001F6 40 000001F7 00FF 000001F9 FF3B 000001FB 0900 000001FD 92 000001FE 0000

Firstsectwrite