Chapter 1
System Firmware’s Missing Link

Hardware: the parts of a computer that can be kicked.

—Jeff Pesis

Booting an Intel architecture platform should be easy. Anyone who thinks that writing an all-purpose Intel® architecture Basic Input Output System (BIOS) and/or an operating system (OS) boot loader from scratch is easy has yet to try it. The complexity and sheer number of documents and undocumented details about the motherboard and hardware components, operating system requirements, industry standards and exceptions, silicon-specific eccentricities beyond the standards, little-known tribal knowledge, basic configuration, compiler nuances, linker details, and variety of applicable debug tools are enormous. While it can be difficult, it doesn’t have to be.

This book is designed to give a background in the basic architecture and details of a typical boot sequence to the beginner firmware developer. Various specifications provide the basics of both the code bases and the standards. While a summary is provided in the chapters below, there is no substitute for reading and comprehending the specifications and developer’s manuals first-hand. This book also provides insights into optimization techniques to the more advanced developers. With the background information, the required specifications on hand, and diligence, many developers can create quality boot solutions. Even if they choose not to create, but to purchase the solution from a vendor, the right information about boot options makes the decision making easier.

Start by Gathering Data

First you must ‘know the ground’; obtaining and using the right data are essential to success. To begin to gather the appropriate documents at the start of the project requires research. Full system initialization is like a large puzzle where someone has hidden some of the pieces:

Motherboard schematics are an absolute must. If you are designing the board, then that is not a problem. If you are reusing an off-the-shelf solution, there is a high likelihood that the vendor who created the board is unwilling to release schematics readily. You can reverse-engineer some of the data, like system management bus addresses, but things like IRQs and GPIOs will be very difficult. If there is an embedded controller in the picture, the number of unknowns increases.

A standard system BIOS today covers at least 70 industry standard specifications alone that can apply to the mainstream client and server boxes commercially available. For application specifications, there could be dozens for a given market segment. If it is a new or emerging type of system, there will be no mature standard and you will be chasing a moving target. Obtaining the list of industry standards that apply is a daunting task and may require some registering and joining to gain access to specifications and/or forums to get your questions answered. Some older specifications are not published and not available today on the Internet.

There are many long-in-the-tooth legacy devices that may need to be initialized, and finding documentation on them is challenging. They may exist only in the dusty drawers of a senior engineer who retired five years ago.

In some cases, nondisclosure agreements (NDAs) must be signed with the various silicon, BIOS, or motherboard vendors. The NDAs can take precious time to obtain and will require some level of legal advice.

UEFI provides a handy API for interfacing to the OS. It has a modular framework and is a viable starting place supporting many industry standards such as ACPI and PCI.

Until now, no single reference manual has documented the required steps needed to boot an Intel architecture system in one place. Nor has anyone detailed the order of initialization to get someone started.

Those who have been exposed to system firmware at a coding level and the inner workings of the black art that is system BIOS understand that it is difficult to explain everything it does, how it does it, or why it should be done in exactly that way. Not many people in the world would have all theanswers to every step in the sequence. Most people who work in the code will want to know just enough to make necessary changes and press on with development or call up their BIOS vendor.

Fortunately, there are many options available when choosing a firmware solution, which we will examine in the next few pages. The more you know about the options, the key players, their history, and the variables, the better decision you can make for your design. The decision will be a combination of arbitrary thought, low-hanging fruit, economies of scale, technical politics, and, of course, money vs. time.

Intel has created an open-source-based system, known as Intel® Boot Loader Development Kit (Intel® BLDK), which provides a turnkey solution without a huge learning curve. Developers can go to www.intel.com and download Intel BLDK for various embedded platforms.

Intel® Quark processor also has a UEFI implementation that is entirely open source and is built using the UEFI framework. This can be found online by searching for Galileo UEFI firmware.

Initialization Roles and Responsibilities

First, let’s get our definitions straight; understand what the industry has been up to, and how we can move forward to make the best decision we can make. Traditionally, a platform based on Intel architecture boots in three steps: system firmware, OS loader, and finally the operating system itself.

System Firmware

The system firmware is a layer between the hardware and the OS that maintains data for the OS about the hardware. As part of the power on self-test (POST), the system firmware begins to execute out of flash to initialize all the necessary silicon components, including the CPU itself and the memory subsystem. Once main memory is initialized, the system firmware is shadowed from ROM into the RAM and the initialization continues. As part of the advanced initialization stages, the system firmware creates tables of hardware information in main memory for the operating system to utilization during its installation, loading, and runtime execution. During POST, hardware workarounds are often implemented to avoid changing silicon or hardware during later design phases. There may be an element of the system firmware that remains active during latter stages to allow for responses to various operating system function calls. The system firmware is customized for the specific hardware needs of the platform and perhaps for a given application. The last thing the system firmware does is hand off control to the OS loader.

System firmware can be constructed in a proprietary legacy code base and/or in a Unified Extensible Firmware Interface (UEFI) framework. Legacy BIOS incorporates a legacy OS interface and follows legacy software interrupt protocols that have been evolving organically since the IBM PC (circa 1981). UEFI is a specification detailing an interface that helps hand off control of the system for the preboot environment—that is, after the system is powered on, but before the operating system starts—to an operating system, such as Microsoft Windows or Linux. UEFI provides an interface between operating systems and platform firmware at boot time, and supports an architecture-independent mechanism for initializing add-in cards (option ROM). We will dig in to the story of how and why legacy BIOS has been converted to UEFI in a minute. A key takeaway is that the system initialization code is either going to be UEFI-based, or legacy-based, or try to support elements of both depending on the operating system requirements.

OS Loader

The OS loader does exactly what its name implies. It is customized with knowledge about the specific operating system, how it is ordered, and what blocks of the OS to pull from the OS storage location. A long list of OS loaders is available in the market today for Linux. We will examine a few of these in later chapters. Microsoft Windows and real-time custom operating systems also have their own flavors. It is possible that the OS loader may be enabled or configured to extend the platform initialization beyond the system firmware’s scope to allow for more boot options than was originally planned.

It is possible, depending on the system architecture and the firmware solutions that you work on, that the OS loader and the system firmware are part of the same binary image located in the same component on the system, or it may be separated.

Operating System

The operating system completes, or in some cases repeats, the initialization of the hardware as it loads and executes the software kernel, services, and device drivers. It potentially loads the human/machine interface (HMI) and finally begins to run the applications. Depending on the application, there are various ways that the OS can be initiated. We will dig into this more in future chapters.

Care should be taken when considering combining elements of various components together as proprietary, and public licenses may prohibit linking the objects together in various ways.

Legacy BIOS Interface, UEFI, and the Conversion

For the three elements to communicate effectively, they share a common set of interfaces. The interfaces have undergone a dramatic change in the past decade. This conversion from legacy BIOS interfaces to UEFI interfaces has not been without some major challenges. During the past ten years, much has been said in industry forums about the platform innovation Framework for EFI, also known as the Tiano code base. When selecting a starting point for development it is important to know the legacy, limitations, and benefits of various solutions.

Tiano Benefits

There are several benefits to UEFI over legacy BIOS:

Location of option ROMs. Legacy option ROMs have been constrained for many years by having to reside below the 1-MB boundary of 16- bit code. Between C0000h and FFFFFh in system memory, all option ROMs including required components like Video BIOS, LAN, SCSI/RAID, manageability, and the system firmware runtime code all had to coexist. In server platforms, this limited the number of add-in cards that could be plugged in. Each of the legacy option ROMs had to do unnatural things to keep their code sizes minimized. A native UEFI system can move the option ROMs above 1 MB, enhancing their capabilities and size. The benefit has real value, especially in larger systems with many add-in devices.

UEFI option ROMs themselves have many benefits over legacy option ROMs. They can be created without the 16-bit code interface, which adds substantial overhead to a legacy option ROM. There is also a UEFI-defined interface to allow for a cohesive user interface instead of creating and maintaining a unique/proprietary command line UI or inventing a GUI, which saves a great deal of size and development overhead in UEFI option ROMs.

Lastly, UEFI option ROMs can also utilize EFI Byte Code (EBC), which allows a single binary to be executed by 64-bit or 32-bit system firmware, thereby reducing validation and inventory issues.

Potential for faster boot. Another advantage of UEFI option ROMs is the ability to initialize only those needed to boot the OS and load the rest later through UEFI function calls from the OS, which speeds the boot process. It requires that the OS utilize a native UEFI interface and that the OS loaders used are also UEFI capable. This benefit has been proved on complex systems between legacy and UEFI solutions, taking the boot speeds from 40 seconds down to 15 seconds in one case.

The modularity of the PEI and DXE modules allows for faster integration of differing code modules. In some cases, this allows for the faster adoption of the code bases’ newer technologies into the platform. It is believed that legacy system BIOS would be unable to integrate new and complex concepts such as Intel® Trusted Execution Technology (Intel® TXT) without extended time in development and validation. Quickly integrating new bus support and in turn new system firmware and OS storage solutions are also a benefit of UEFI. It has been proved that legacy code bases can have difficulty integrating newer technologies.

UEFI Shell. The shell was designed to support features from DOS or UNIX environments in order to be a potential replacement for these older OS. Many of the same commands are supported. Simple native applications similar to older OS applications can be created to run single function operations for the platform or provide diagnostics or a flash upgrade path. UEFI shells have become standardized in the past few years. For more information on shells, please refer to “Harnessing the UEFI Shell” or proceed to Chapter 9.

Scalability. Having an open-source system-firmware offering supported by a community of many computing companies, including BIOS vendors, OEMs, motherboard manufacturers, add-in card vendors, OS vendors, and silicon vendors, can be very advantageous when starting and maintaining your own development in the long term. If you’re using a legacy proprietary code base, the learning curve exists as with any code base, and there are continuous improvements and maintenance costs/time. The solution may not scale quite so easily between computing segments.

Security. In the most recent updates of the UEFI development kit (UDK2015), Internet Protocol v6 is supported. UEFI variables can be securely stored and easily authenticated. A new UEFI security binary can be added to allow for hashing. UEFI option ROMs that are added in can be signed and the signatures checked before execution. As new operating systems come online, security will be a vital requirement across most market segments. UEFI is ready for the tasks.

Longevity. UEFI has legs for the foreseeable future. Legacy is legacy for a reason, and continuing to support that legacy adds costs and complexity.

There are some clear advantages to UEFI: faster boot, modularity, DOS replacement, scalability, security, overcoming the limitations of legacy PC AT interfaces, and longevity.

Previous UEFI Challenges

In the past, there have been some challenges early in the adoption of UEFI. While these challenges have been discussed and dealt with at an industry level, some still see the need to address bringing up these points of debate. As embedded architecture moves forward into new segments, it is vital that open and honest dialogue can occur about the firmware solutions that exist and their pros and cons. As these perceptions may still exist, let’s review the points and discuss how they have been eliminated or minimized over time.

Maturity: Like any new code base, UEFI source initially lacked 20 years of industry validation and experience. It did not consider every known add-in card workaround or industry standard. It was not ported to many environments. It was not yet validated over the long term across multiple generations of products (and developers). Over the past decades, this has changed. The solution is now well validated by many industry teams and groups. Workarounds have been included, the industry standards have been adhered to, and new environments have been adapted.

Some tend to adapt to any new technology slowly. Despite the benefits of a new standard, a new code base takes time to adopt and adapt to, in part due to NIH (not invented here) syndrome. In other cases, it has been a matter of having to support a code-base change while maintaining the legacy one. It takes several cycles to convert before the technology is broadly embraced.

One common belief of early adopters has been that handwritten assembly code would always outperform C code. Intel and other maintainers of compilers have advanced their craft, and these compilers can now surpass and put to rest the ASM-only ideology.

The original Tiano code base was not constructed like a traditional system BIOS in the core-to-platform-to-motherboard architecture. Instead, it was constructed as an OS might be, with a core-to-bus-to-device- driver model, which proved difficult to adapt to some new segments. The newer version of the code base, EDK II, has evolved to facilitate development with input from major BIOS vendors and OEMs.

Persistence of Change

In the end, what started out as an idea exclusive to Itanium® began to see early UEFI projects started in mainstream computing. First in the mobile-computing segments, where UEFI was designed into many laptop computers starting around 2002. It then spread to adjacent segments in desktop machines, and is now implemented in a broad range of products from high-end servers to embedded devices. And not just Intel Architecture, but ARM architecture as well.

The Next Generation

As with any first-generation product, changes and improvements to the design were made to meet the industry needs. Working together within the UEFI forum, where most major players in the computing business are working on the next-generation firmware architectures and implementations of UEFI open source code base, the team has produced the EDK II. It has taken many years to work through and prioritize some of the improvements and changes required to help the industry to evolve and remain vibrant. Major computing manufacturing companies and BIOS vendors are ready to ship products on this new code base, which promises more flexibility and streamlined features, including GCC (GNU Compiler Collection) compatibility.

Also, while being deep in complexity, the documentation of the newer versions of the code is unsurpassed within the industry. The API today is more robust and usable than in previous generations and more easily adapted to new and upcoming operating systems.

This was the history of the major conversion and some of the reasons you can decide to select a standard UEFI implementation or a different firmware technology to start on for development. Strategically, EDK II easily makes the best long-term solution. Let’s look at the state of the commercial BIOS business that has emerged from the transition.

Commercial BIOS Business

Looking at commercial independent BIOS vendors (IBVs), it’s evident the industry has been evolving since 1983, when Phoenix Technologies Limited (Phoenix) shipped its first BIOS. Like any industry, it has grown and shrunk, and new companies have started while major competitive players have merged.

Award

Award BIOS was started in Taiwan and with its unique per-unit license quickly took advantage of local tax loopholes to gain the edge at local motherboard vendors. The simplicity and affinity of the Award code base has kept the product entrenched in various motherboard manufacturers years after Phoenix had discontinued the product.

General Software

Formed in 1989 by former Windows NT architect Steve Jones, General Software created unique and dynamic solutions for the embedded segment. General Software has in the past been one of the major players in the embedded space but did not penetrate much into the mainstream markets.

Phoenix Technologies Limited

Phoenix, headquartered in Milpitas, CA, was founded in 1979 (pre-BIOS). In 1998, Phoenix purchased the Award BIOS, and in 2007 acquired General Software. By combining the code bases and resources of the three original companies, Phoenix BIOS has a large amount of intellectual property to draw from as it moves forward. Phoenix has gone through great changes in the past few years, including branching out into adjacent software ventures.

American Megatrends Inc.

AMI was founded in 1985 by Subramanian Shankar and has created a large variety of solutions, including BIOS, software diagnostics, RAID technology, and hardware platforms. Beyond having a broad base of products, AMI is the only consistently privately owned commercial BIOS company. Its products today include the AMI 8 legacy core and the AMI Aptio core (a UEFI base first demonstrated in 2004) and AMI-Diags, all focused on system firmware.

Insyde Software

Insyde is a Taiwanese BIOS vendor formed in 1998, brought forth from the ashes of SystemSoft. Insyde was the first to launch a UEFI solution in the BIOS industry, Insyde H20. They have expanded to include offerings in multiple segments and are today the only vendor in the Itanium segment. Besides UEFI Framework base BIOS, Insyde also offers UEFI applications and keyboard firmware.

ByoSoft

In early 2006, Nanjing ByoSoft Co., Ltd. (ByoSoft), was established in China. In 2008, ByoSoft became one of the four independent BIOS vendors in the world providing professional UEFI BIOS products and service and the only one based in mainland China. While they are the new kid on the block, they have many long-time BIOS engineers working for them and major companies signed up.

Value of BIOS

The bill of material (BOM) impact of a system BIOS from segment to segment can differ greatly depending on a variety of factors. The business model can be based on a combination of non-recurrent engineering (NRE) and/or royalty per motherboard. Depending on:

Original innovation

Porting cost

Source level access

Support need

Expected volume

Customization requirements

Vendor/supplier history

This is not unlike many other free market dynamics. If volume pricing can apply, royalties per board could be a relatively low percentage of the bill of materials (BOM) cost. When volumes do not apply, then royalties per board can rise to affect the BOM. Embedded systems customers often must pay a much higher cost per board because of the diverse nature of the business segments, limited volume, and high-touch model for adapting the mainstream products for custom applications.

Proprietary Solutions

Beyond the four commercial BIOS companies mentioned above, it is possible that many name-brand computer manufacturers have teams that can and/or do write their own proprietary BIOS. Over the years, many have created their own BIOS, starting with IBM and the IBM PC. In some cases, separate business units within very large companies have even created their own solutions.

At IBM, a team of developers created a boot firmware for its new desktop machine in August, 1981, which became known as a BIOS. Today, IBM has a choice of who they use for which product, internal or external.

In 1982, Compaq wrote the first BIOS specification by reverse- engineering the IBM BIOS with one team that wrote the specification and then handing the specification to another team, which in turn wrote the Compaq portable PC firmware from scratch.

Today, HP does their own BIOS and utilizes BIOS vendors depending on the product lines.

While Intel currently employs the maintainers of the UEFI solutions at www.tianocore.org, it does not produce commercially available BIOS, not counting Intel-branded motherboards.

Other large computer and motherboard manufacturers around the world have the capability to develop their own solutions, and often opt to employ their favorite BIOS vendors for core and tool maintenance.

Apart from front-end system firmware, server manufacturers in particular have extensive value-add firmware-based solutions for baseboard management controllers (BMCs), which are embedded controllers that control the back-end subsystem to enhance a server board’s ability to be remotely managed and for increased fault tolerance.

Making a Decision on Boot Firmware

Whether a company works in the private, public, or academic space, the firmware make-or-buy decision can be difficult without proper insight. In the embedded space, many smaller OEMs maintain a small staff to manage and/or develop their system firmware. Depending on the level of experience and number of designs they have to support, they may decide to implement a commercial BIOS product or they may try to create their own.

When a BIOS vendor is not an option, they must roll up their sleeves and search for alternatives. In the education arena, software engineering, computer engineering, and electrical engineering students all learn a certain level of low-level firmware coding as part of just a few of their classes, but most curriculums don’t include a class that takes the student through the full experience of system firmware development. Except for some graduate level projects, most students do not get to develop their own solutions from scratch.

There are three basic options: BIOS vendor, reuse/borrow from open source, from scratch.

Consider Using a BIOS Vendor

Talking to a BIOS vendor is a great idea when the situation demands product- ready solutions, and the return on investment merits it. To get starter code from a BIOS vendor normally requires various levels of licenses and agreements for evaluation, production, and follow-on support. The business and legal negotiations can take time, so if you want to implement this, you should start early. A commercial BIOS comes with a varying amount of nonrecurring engineering (NRE) and/or royalties per unit or subscription costs. If you choose this route, there is a very high likelihood that you are getting exactly what you need to get started and get to a successful production cycle. You can outsource the duties and responsibilities entirely if you choose to. First- generation products often have hiccups and, even if you are not inclined to take the easy way out on a regular basis, you should consider what BIOS vendors can offer. Many successful and established computer OEM development teams employ BIOS vendors to provide a base level of software core competency, basic OS support, tools, and on-call support while the in-house developers focus at the finer details and ensure that the job is done on schedule. BIOS vendors may offer starter kits with a lesser number of features and limited support, which smaller companies or individuals can take advantage of if they do not have the time to dive deep into the firmware realm. As everyone’s concept of what constitutes cheap versus expensive varies, product teams should weigh their options and the return on investment levels and make the right decision for them for a given project. The next project or another parallel project in the pipeline may require another solution with entirely different requirement sets. Scalability may be something that internal teams cannot meet on their own due to a tight production cycle.

Some say that BIOS vendors (and BIOS) are becoming obsolete, especially considering silicon vendors supporting boot loaders, but this is not true. People said the same thing when Tiano originally came out 10 years ago—“say goodbye to BIOS.” Some thought it would come true when Linux BIOS started, but they too have been disappointed. If the Linux multiverse is anything to go by, commercial distribution houses such as Red Hat, offering commercially, prepackaged products and support, continue to thrive even when parallel royalty-free and subscription-free alternatives exist on the same kernel and with many of the same products. Why? Because Linux isn’t free—people must roll up their sleeves and do the work upfront and continue to maintain it. The same thing can be said about system firmware. Commercial BIOS vendors like Insyde, Phoenix BIOS, AMI, ByoSoft, and others will continue to provide turn-key product quality and services to the computing industry in the future, regardless of the codebase being used. They provide value-added products, plain and simple.

Consider Open-Source Alternatives

For those who choose to take the plunge to create their own solution in whole or in part, free and open-source alternatives can be downloaded from the Web that offer a starting point and/or reference. Two of the well-known open-source products available to the market are Coreboot and Tiano.

Tiano

The Tiano core uses a BSD license and provides a flexible framework. Developers normally must get certain initialization codes from the silicon vendor individually, or they must reverse-engineer code that already exists on other platforms. Tiano, by default, also lacks the needed legacy interfaces to allow many older operating systems or PCI device option ROMs to be used. Developers can choose to create a Compatibility Support Module for legacy operating system based on the IBM BIOS specification. Tiano does have enough documentation, as well as the UEFI API, which replaces the legacy interface, and the UEFI drivers, which replace legacy option ROMs; overall more robust.

Coreboot

Formerly Linux BIOS, Coreboot provides source code under a GPL license. It has grown and evolved since starting out at Cluster Research Lab at the Advanced Computing Laboratory at Los Alamos National Laboratory. It got a lift from Google in the last 5 years as a few of the leads joined the company.

Uboot

Also known as Das Universal Boot, or Das U-boot, Uboot is owned by DENX software and is distributed under a GPL license. Uboot is broadly used in embedded devices.

For more information about these and other alternatives, like Aboot, please explore the web.

Consider Creating Something from Scratch

Regardless of the challenges, it is possible to start coding from 0s and 1s, in assembly, or in C, or PERL, and so on. The language doesn’t matter. You would have had to take on the tasks of initialization one at a time, and likely have a tightly bundled RTOS or native-mode application. It is possible to boot Intel architecture completely from scratch. You can also use the open sources as reference code (licenses included). It may take an NDA with a few companies to get the necessary details of secret sauce bits to toggle on more advanced machines. Having other options available with the benefits of some of these have already been outlined above. Starting fresh is not the best option once you step back and look at the alternatives and trade-offs. But there are more options out there. . . .

Consider a Native Boot Loader for Intel ® Architecture

When market needs precipitated a native boot loader, Intel created the Intel Boot Loader Development Kit (Intel BLDK) to provide a way to bootstrap firmware developers new to Intel architecture. It was a good experiment and provided support for a few Atom-based embedded platforms. Providing a combination of source, binary, tools, and documentation, BLDK allows embedded firmware developers to not only debug and boot their platform, but customize and optimize it for their basic production needs. It is designed to do the basic silicon initialization required to bring the processor out of Reset, enable the system’s main memory, enable the device path to the target OS storage device, fetch the initial sector of the OS, and hand control to the OS. It provides a great reference for people new to the firmware and BIOS industry.

It is for system firmware developers working on platforms for embedded devices based on Intel® Atom™ Processors. Students can gain an insight into what happens before the OS takes over and in the background while the OS runs. System firmware and hardware designers can grasp the level of work required to perform Intel architecture initialization.

Intel BLDK lacks extended features that would allow the user to run many standard off-the-shelf operating systems. As BLDK is an extendable kit, system developers are free to make their own additions and modifications to take advantage of all the latest and greatest technologies coming from Intel. It however doesn’t have enough platform support to be considered universal.

Just Add Silicon Initialization

The Intel® Firmware Support Package (FSP) provides chipset and processor initialization in a format that can easily be incorporated into many existing boot loaders. FSP will perform all the base initialization steps for Intel silicon, including initialization of the CPU, memory controller, chipset and certain bus interfaces, if necessary. The initialization will enable enough hardware to allow the boot loader to load an operating system. FSP is not a stand-alone boot loader as it does not initialize non-Intel components, conduct broad bus enumeration, discover devices in the system, or support all industry standard initialization. FSP must be integrated into a host boot loader, such as those open-source solutions mentioned above, to carry out full boot loader functions.

Summary

Booting Intel architecture should be easy. While open source provides many advances in case you need to know the nuts and bolts, this book provides that background. Most of the basics in the system firmware space are not something taught in college; they are learned through on-the-job training.

Options are available when choosing a firmware solution as a starting point. The more that you know about them, as well as about the key players, their history, and the variables, the better decision you can make for your current and future designs. The decision will be a combination of arbitrary thought, low-hanging fruit, economies of scale, technical politics, and, of course, money versus time.

In the following chapters, we describe details of the typical Intel architecture boot flow and then detail how to port and debug an Intel architecture motherboard and add custom initialization for your own design. We will examine different OS loader support for typical use cases. Hopefully this gives you an appreciation of the scope involved and gives you some ideas.

As the title implies, this book is a supplement for embedded developers. We will use Intel BLDK as an example, but the following chapters apply to all initialization solutions. The Intel® Galileo board also has full UEFI source, which is available on GitHub if developers want to play with these concepts and develop their own bootloaders.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.72.245