Preface

Greetings!

You’ve probably asked yourself at least once how an operating system is written from the ground up. You might even have years of programming experience under your belt, yet your understanding of operating systems may still be a collection of abstract concepts not grounded in actual implementation. To those who’ve never built one, an operating system may seem like magic: a mysterious thing that can control hardware while handling a programmer’s requests via the API of their favorite programming language. Learning how to build an operating system seems intimidating and difficult; no matter how much you learn, it never feels like you know enough. You’re probably reading this book right now to gain a better understanding of operating systems to be a better software engineer.

If that is the case, this book is for you. By going through this book, you will be able to find the missing pieces that are essential and enable you to implement your own operating system from scratch! Yes, from scratch, without going through any existing operating system layer to prove to yourself that you are an operating system developer. You may ask,“Isn’t it more practical to learn the internals of Linux?”.

Yes…

and no.

Learning Linux can help your workflow at your day job. However, if you follow that route, you still won’t achieve the ultimate goal of writing an actual operating system. By writing your own operating system, you will gain knowledge that you will not be able to glean just from learning Linux.

Here’s a list of some benefits of writing your own OS:

Why another book on Operating Systems?

There are many books and courses on this topic made by famous professors and experts out there already. Who am I to write a book on such an advanced topic? While it’s true that many quality resources exist, I find them lacking. Do any of them show you how to compile your C code and the C runtime library independent of an existing operating system? Most books on operating system design and implementation only discuss the software side; how the operating system communicates with the hardware is skipped. Important hardware details are skipped, and it’s difficult for a self-learner to find relevant resources on the Internet. The aim of this book is to bridge that gap: not only will you learn how to program hardware directly, but also how to read official documents from hardware vendors to program it. You no longer have to seek out resources to help yourself interpret hardware manuals and documentation: you can do it yourself. Lastly, I wrote this book from an autodidact’s perspective. I made this book as self-contained as possible so you can spend more time learning and less time guessing or seeking out information on the Internet.

One of the core focuses of this book is to guide you through the process of reading official documentation from vendors to implement your software. Official documents from hardware vendors like Intel are critical for implementing an operating system or any other software that directly controls the hardware. At a minimum, an operating system developer needs to be able to comprehend these documents and implement software based on a set of hardware requirements. Thus, the first chapter is dedicated to discussing relevant documents and their importance.

Another distinct feature of this book is that it is “Hello World” centric. Most examples revolve around variants of a “Hello World” program, which will acquaint you with core concepts. These concepts must be learned before attempting to write an operating system. Anything beyond a simple “Hello World” example gets in the way of teaching the concepts, thus lengthening the time spent on getting started writing an operating system.

Let’s dive in. With this book, I hope to provide enough foundational knowledge that will open doors for you to make sense of other resources. This book will be beneficial to students who’ve just finished their first C/C++ course greatly. Imagine how cool it would be to show prospective employers that you’ve already built an operating system.

Prerequisites

In general, I assume that the reader has basic C programming knowledge, and can use an IDE to build and run a program.

What you will learn in this book

What this book is not about

What is new in the second edition

The first edition was written against Ubuntu 16.04 and gcc 5.4. A few years later, readers who typed the commands in the book got different output: compilers started producing position-independent executables by default, the linker started rejecting the linker script of chapter 8, and nobody could tell whether the book or their machine was at fault. Part 3 was also never finished; it stopped at a list of chapter headings. This edition fixes both problems:

The organization of the book

Chapter 0

sets up the development environment: the tools, the compiler flags used throughout the book and a container image with the exact tool versions that produced the listings. It ends with a smoke test that boots the bootloader of chapter 7, so that any installation problem is found before chapter 1.

Part 1

provides a foundation for learning operating system.

Part 2

presents how to write a bootloader to bootstrap a kernel. Hence the name “Groundwork”. After mastering this part, the reader can continue with the next part, which is a guide for writing an operating system. However, if the reader does not like the presentation, he or she can look elsewhere, such as OSDev Wiki: http://wiki.osdev.org/.

Part 3

provides guidance on how to write an operating system, as you should implement an operating system on your own and be proud of your creation. The guidance consists of simpler and coherent explanations of necessary concepts, from hardware to software, to implement the features of an operating system. Without such guidance, you will waste time gathering information spread through various documents and the Internet. Each chapter names the sections of the Intel manuals to read, adds one feature to the kernel started in Part 2, shows how to debug it with gdb and QEMU, and ends with exercises.

Appendices

Appendix A is a reference of the toolchain and the compiler flags, and of the editions of the manuals the book cites. Appendix B lists the errata of the first edition. Appendix C is a minimal, tested long-mode bootstrap. Appendix D is a reading order for the Intel and AMD manuals, chapter by chapter. Appendix E holds the answers to the “Check your understanding” questions. A glossary closes the book. (The GNU Make and gdb script summaries stay in chapter 7, where they are first needed.)

Acknowledgments

Thank you, my beloved family. Thank you, the contributors.