박종훈 기술블로그

build linux kernel from macbook pro m1

I recently started an offline group study.
One of the things going on in the study is an operating system study (We are using this book).

At the end of Chapter 2, there is a section that describes the Linux kernel build.

linux symbol

While I was making a presentation slide, I was like, 'Is this really going to work?' It occurred to me that.

thinking emoji

So I tried it.
I shouldn't have tried that

Try building the Linux kernel

The order introduced in the book was as follows.

  1. Download the Linux source code from http://www.kernel.org.
  2. Configure the kernel using the “make menuconfig” command. This step creates a .config configuration file.
  3. Compile the main kernel using the “make” command. The make command compiles the kernel based on the configuration parameters identified in the .config file to create a kernel image, the vmlinuz file.
  4. Compile the kernel module using the “make modules” command. Like kernel compilation, module compilation depends on configuration parameters specified in the .config file.
  5. Install the kernel module to vmlinuz using the “make modules install” command.
  6. Enter the “make install” command to install the new kernel on your system.

And I followed this order

Caution

  • Since the mac m1 is arm-based, I started with the expectation that it would be difficult in the process.
  • I'm trying to organize it in writing to see if there is anyone who makes a unique attempt like me. In my own search, I didn't find much information.
  • I'm not familiar with C. It's all I studied in my first year of university. That's why the following contents have been solved in a bad way.

1. Download the Linux source code from http://www.kernel.org.

kernel downlaod page

Latest Release seems to mean the Stable version.
Download and decompress it in a good place to work.

2. Configure the kernel using the “make menuconfig” command.

There are things to do from here.

Since I usually use the make command during the development process, I thought there would be no problem, but the problem occurs with the make command.

When I run it, I get the following error:
Makefile:15: *** GNU Make >= 3.82 is required. Your Make version is 3.81. Stop

The latest version of make is available through brew. Let's set environment variables as well.

brew install make
export PATH="/usr/local/opt/make/libexec/gnubin:$PATH"

If you check the version after installing the latest version with brew, you can see that it has been upgraded to the 4.x version.
make version

Then install the following things

brew install gcc-arm-embedded --cask
brew install cmake autoconf libtool gcc automake openssl
brew link openssl --force

if you don't install
linker error
This error will occur.

After completing the installation, you can finally enter the menu setting page.

menuconfig

Since I don't know anything about these setting values, I created a config file with the default setting values.

3. Compile the main kernel using the “make” command.

This process took quite a long time.
I think it was more difficult because I didn't know much about C.

This part referenced a lot of blog post written down in the reference at the bottom.

fatal error: 'elf.h' file not found

In mac, elf.h is not provided by default.

https://gist.github.com/mlafeldt/3885346
You can create elf.h with the above code.

or,

curl https://gist.githubusercontent.com/mlafeldt/3885346/raw/elf.h | tee /usr/local/include/elf.h

If you type this command, it will be created at once.

But the problem was, I don't know why, but my code couldn't load the header file normally.
(Maybe it's because I don't know how to use gcc's I option properly.)

So move the header file into the kernel project,
And it was modified to include the local header file.
(Change braket to double quote. , https://stackoverflow.com/a/3162067)

I edited about 5 files.

typedef redefinition with different types ('struct uuid_t' vs '__darwin_uuid_t' (aka 'unsigned char[16]'))

/* UUID types for backward compatibility, don't use in new code */
typedef struct {
        __u8 b[16];
} guid_t;

#define uuid_t compat_uuit_t

typedef struct {
        __u8 b[16];
} uuid_t;

The file structure of the post I referenced and my computer was a little different, and the code included #endif, so I thought, 'Where does the if begin?' I thought a lot about it.

I just did the above and it built without problems.

The key seems to be adding #define uuid_t compat_uuit_t.

openssl setup issue

Similar to elf.h earlier, my computer could not import the openssl header file.
I was repeating builds and modifications, and correcting errors.
There was no end, so I stopped the work and looked for how many places needed to be corrected.
About 500+ places needed fixing...

I thought it was not something a person would do, so I made batch changes using regex as a command.

build success

After solving these and other issues, a vmlinux file was created.

The build itself seems to have taken about 10 minutes.

vmlinux

Conclusion: Don't Build the Linux Kernel on Apple Silicon

Reference

Setting up Mac M1 for Linux Kernel/ Device Driver Development