mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-24 14:56:49 +03:00
Move to clang, no longer ship prebuilt binary, embed bootloader into the installer and provide a way to install the installer
This commit is contained in:
parent
ea62cf37c7
commit
7bde0c80ca
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,8 @@
|
|||||||
/**/*.o
|
/**/*.o
|
||||||
|
/**/*.a
|
||||||
|
/**/*.bc
|
||||||
/**/*.bin
|
/**/*.bin
|
||||||
|
/**/*.elf
|
||||||
/**/*.img
|
/**/*.img
|
||||||
/bochsout.txt
|
/bochsout.txt
|
||||||
/bx_enh_dbg.ini
|
/bx_enh_dbg.ini
|
||||||
|
41
Makefile
41
Makefile
@ -1,17 +1,32 @@
|
|||||||
|
DESTDIR =
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
OS := $(shell uname)
|
OS := $(shell uname)
|
||||||
CC = cc
|
CC = clang
|
||||||
|
OBJCOPY = llvm-objcopy
|
||||||
|
CFLAGS = -O2 -pipe -Wall -Wextra
|
||||||
|
|
||||||
.PHONY: all clean echfs-test ext2-test test.img
|
.PHONY: all install clean echfs-test ext2-test test.img
|
||||||
|
|
||||||
all:
|
all: limine-install
|
||||||
$(MAKE) -C src all
|
|
||||||
cp src/limine.bin ./
|
install: all
|
||||||
|
install -s limine-install $(DESTDIR)$(PREFIX)/bin/
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
rm -f limine-install
|
||||||
$(MAKE) -C src clean
|
$(MAKE) -C src clean
|
||||||
|
|
||||||
limine-install: limine-install.c
|
src/limine.bin:
|
||||||
$(CC) limine-install.c -o limine-install
|
$(MAKE) -C src all
|
||||||
|
|
||||||
|
limine-install: src/limine.bin limine-install.c
|
||||||
|
$(CC) $(CFLAGS) -c limine-install.c -o limine-install.o
|
||||||
|
# FIXME: GNU objcopy supports `-O default` but for some stupid reason
|
||||||
|
# llvm-objcopy does not. This needs to be worked around.
|
||||||
|
# For now hardcode elf64-x86-64.
|
||||||
|
$(OBJCOPY) -I binary -O elf64-x86-64 src/limine.bin limine.o
|
||||||
|
$(CC) $(CFLAGS) limine.o limine-install.o -o limine-install
|
||||||
|
|
||||||
test.img:
|
test.img:
|
||||||
rm -f test.img
|
rm -f test.img
|
||||||
@ -26,15 +41,15 @@ else ifeq ($(OS), FreeBSD)
|
|||||||
sudo mdconfig -d -u md9
|
sudo mdconfig -d -u md9
|
||||||
endif
|
endif
|
||||||
|
|
||||||
echfs-test: limine-install test.img all
|
echfs-test: limine-install test.img
|
||||||
$(MAKE) -C test
|
$(MAKE) -C test
|
||||||
echfs-utils -m -p0 test.img quick-format 32768
|
echfs-utils -m -p0 test.img quick-format 32768
|
||||||
echfs-utils -m -p0 test.img import test/test.elf boot/test.elf
|
echfs-utils -m -p0 test.img import test/test.elf boot/test.elf
|
||||||
echfs-utils -m -p0 test.img import test/limine.cfg limine.cfg
|
echfs-utils -m -p0 test.img import test/limine.cfg limine.cfg
|
||||||
./limine-install src/limine.bin test.img
|
./limine-install test.img
|
||||||
qemu-system-x86_64 -hda test.img -debugcon stdio -enable-kvm
|
qemu-system-x86_64 -hda test.img -debugcon stdio -enable-kvm
|
||||||
|
|
||||||
ext2-test: limine-install test.img all
|
ext2-test: limine-install test.img
|
||||||
$(MAKE) -C test
|
$(MAKE) -C test
|
||||||
rm -rf test_image/
|
rm -rf test_image/
|
||||||
mkdir test_image
|
mkdir test_image
|
||||||
@ -49,10 +64,10 @@ ext2-test: limine-install test.img all
|
|||||||
sudo umount test_image/
|
sudo umount test_image/
|
||||||
sudo losetup -d `cat loopback_dev`
|
sudo losetup -d `cat loopback_dev`
|
||||||
rm -rf test_image loopback_dev
|
rm -rf test_image loopback_dev
|
||||||
./limine-install src/limine.bin test.img
|
./limine-install test.img
|
||||||
qemu-system-x86_64 -hda test.img -debugcon stdio
|
qemu-system-x86_64 -hda test.img -debugcon stdio
|
||||||
|
|
||||||
fat32-test: limine-install test.img all
|
fat32-test: limine-install test.img
|
||||||
$(MAKE) -C test
|
$(MAKE) -C test
|
||||||
rm -rf test_image/
|
rm -rf test_image/
|
||||||
mkdir test_image
|
mkdir test_image
|
||||||
@ -77,5 +92,5 @@ else ifeq ($(OS), FreeBSD)
|
|||||||
sudo mdconfig -d -u md9
|
sudo mdconfig -d -u md9
|
||||||
endif
|
endif
|
||||||
rm -rf test_image loopback_dev
|
rm -rf test_image loopback_dev
|
||||||
./limine-install src/limine.bin test.img
|
./limine-install test.img
|
||||||
qemu-system-x86_64 -hda test.img -debugcon stdio
|
qemu-system-x86_64 -hda test.img -debugcon stdio
|
||||||
|
49
README.md
49
README.md
@ -16,23 +16,35 @@ x86/x86_64 BIOS Bootloader
|
|||||||
* MBR
|
* MBR
|
||||||
* GPT
|
* GPT
|
||||||
|
|
||||||
## How to use
|
## Building
|
||||||
This repository contains a prebuilt version of Limine so building it won't be necessary.
|
|
||||||
|
|
||||||
In order to install Limine on a MBR device (which can just be a raw image file), build the
|
### Dependencies
|
||||||
`limine-install` program using `make limine-install`, then run the resulting executable as such:
|
To build Limine, it is necessary to have an LLVM/Clang toolchain installed.
|
||||||
|
More specifically, the following programs need to be present: `clang`, `llvm-objcopy`,
|
||||||
|
`llvm-link`, `opt`, `ld.lld`.
|
||||||
|
Furthermore, `nasm` also needs to be installed.
|
||||||
|
`curl`, `tar`, and `zstd` need to be installed for retrieving `libgcc.a` during build.
|
||||||
|
|
||||||
|
### Compiling
|
||||||
|
A simple `make` and `make install` will suffice. Use the PREFIX variable with
|
||||||
|
`make install` to specify where to install `limine-install`. It defaults to
|
||||||
|
`/usr/local`.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
In order to install Limine on a MBR device (which can just be a raw image file),
|
||||||
|
run the `limine-install` as such:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./limine-install ./limine.bin <path to device/image>
|
limine-install <path to device/image>
|
||||||
```
|
```
|
||||||
|
|
||||||
If using a GPT formatted device, it will be necessary to create an extra partition
|
If using a GPT formatted device, it will be necessary to create an extra partition
|
||||||
(of at least 32K in size) to store stage 2 code. Then it will be necessary to tell
|
(of at least 32K in size) to store stage 2 code. Then it will be necessary to tell
|
||||||
the install script where this partition is located by specifying the start sector.
|
`limine-install` where this partition is located by specifying the start sector.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
fdisk <device> # Create bootloader partition using your favourite method
|
fdisk <device> # Create bootloader partition using your favourite method
|
||||||
./limine-install ./limine.bin <path to device/image> <start sector of boot partition>
|
limine-install <path to device/image> <start sector of boot partition>
|
||||||
```
|
```
|
||||||
|
|
||||||
Then make sure the device/image contains at least 1 partition formatted in
|
Then make sure the device/image contains at least 1 partition formatted in
|
||||||
@ -58,33 +70,12 @@ echfs-utils -m -p0 test.img import path/to/limine.cfg limine.cfg
|
|||||||
echfs-utils -m -p0 test.img import path/to/kernel.elf kernel.elf
|
echfs-utils -m -p0 test.img import path/to/kernel.elf kernel.elf
|
||||||
echfs-utils -m -p0 test.img import <path to file> <path in image>
|
echfs-utils -m -p0 test.img import <path to file> <path in image>
|
||||||
...
|
...
|
||||||
./limine-install $THIS_REPO/limine.bin test.img
|
limine-install test.img
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
One can get `echfs-utils` by installing https://github.com/qword-os/echfs.
|
One can get `echfs-utils` by installing https://github.com/qword-os/echfs.
|
||||||
|
|
||||||
## Building from source
|
|
||||||
In order to hack Limine, one must build the GCC toolchain from source first.
|
|
||||||
|
|
||||||
To do so, run the `make_toolchain.sh` script from within the `toolchain` directory;
|
|
||||||
keep in mind that the script takes `MAKEFLAGS` as an argument.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd toolchain
|
|
||||||
./make_toolchain.sh -j4
|
|
||||||
```
|
|
||||||
|
|
||||||
After that is done, simply run `make` in the root of the repo to generate
|
|
||||||
`limine.bin`.
|
|
||||||
|
|
||||||
### Building from source with Clang
|
|
||||||
It is also possible to build Limine with Clang, using the following make command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make CC="clang --target=i386-elf"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Discord server
|
## Discord server
|
||||||
We have a Discord server if you need support, info, or you just want to
|
We have a Discord server if you need support, info, or you just want to
|
||||||
hang out: https://discord.gg/QEeZMz4
|
hang out: https://discord.gg/QEeZMz4
|
||||||
|
@ -4,53 +4,45 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
extern char _binary_src_limine_bin_start[];
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc < 3) {
|
if (argc < 2) {
|
||||||
printf("Usage: %s <path to bootloader binary> <device> [stage2 start sector]\n", argv[0]);
|
printf("Usage: %s <device> [stage2 start sector]\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *ql2_bin = fopen(argv[1], "rb");
|
FILE *device = fopen(argv[1], "r+b");
|
||||||
if (ql2_bin == NULL) {
|
|
||||||
perror("Error: ");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *device = fopen(argv[2], "r+b");
|
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
perror("Error: ");
|
perror("Error: ");
|
||||||
fclose(ql2_bin);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t stage2_sect = 1;
|
uint32_t stage2_sect = 1;
|
||||||
if (argc >= 4)
|
if (argc >= 3)
|
||||||
sscanf(argv[3], "%" SCNu32, &stage2_sect);
|
sscanf(argv[2], "%" SCNu32, &stage2_sect);
|
||||||
|
|
||||||
|
// Save the original partition table of the device
|
||||||
char orig_mbr[64];
|
char orig_mbr[64];
|
||||||
fseek(device, 446, SEEK_SET);
|
fseek(device, 446, SEEK_SET);
|
||||||
fread(orig_mbr, 1, 64, device);
|
fread(orig_mbr, 1, 64, device);
|
||||||
|
|
||||||
char ql2_bootsect[512];
|
// Write the bootsector from the bootloader to the device
|
||||||
fseek(ql2_bin, 0, SEEK_SET);
|
|
||||||
fread(ql2_bootsect, 1, 512, ql2_bin);
|
|
||||||
fseek(device, 0, SEEK_SET);
|
fseek(device, 0, SEEK_SET);
|
||||||
fwrite(ql2_bootsect, 1, 512, device);
|
fwrite(&_binary_src_limine_bin_start[0], 1, 512, device);
|
||||||
|
|
||||||
char *ql2_stage2 = malloc(63 * 512);
|
// Write the rest of stage 2 to the device
|
||||||
fseek(ql2_bin, 512, SEEK_SET);
|
|
||||||
fread(ql2_stage2, 63, 512, ql2_bin);
|
|
||||||
fseek(device, stage2_sect * 512, SEEK_SET);
|
fseek(device, stage2_sect * 512, SEEK_SET);
|
||||||
fwrite(ql2_stage2, 63, 512, device);
|
fwrite(&_binary_src_limine_bin_start[512], 63, 512, device);
|
||||||
free(ql2_stage2);
|
|
||||||
|
|
||||||
|
// Hardcode in the bootsector the location of stage 2
|
||||||
fseek(device, 0x1b0, SEEK_SET);
|
fseek(device, 0x1b0, SEEK_SET);
|
||||||
fwrite(&stage2_sect, 1, 4, device);
|
fwrite(&stage2_sect, 1, sizeof(uint32_t), device);
|
||||||
|
|
||||||
|
// Write back the saved partition table to the device
|
||||||
fseek(device, 446, SEEK_SET);
|
fseek(device, 446, SEEK_SET);
|
||||||
fwrite(orig_mbr, 1, 64, device);
|
fwrite(orig_mbr, 1, 64, device);
|
||||||
|
|
||||||
fclose(ql2_bin);
|
|
||||||
fclose(device);
|
fclose(device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
40
src/Makefile
40
src/Makefile
@ -1,46 +1,50 @@
|
|||||||
CC = ../toolchain/bin/i386-elf-gcc
|
OPT_LEVEL = z
|
||||||
LD = ../toolchain/bin/i386-elf-gcc
|
CFLAGS = -pipe -Wall -Wextra
|
||||||
|
|
||||||
CFLAGS = -flto -Os -pipe -Wall -Wextra
|
|
||||||
|
|
||||||
INTERNAL_CFLAGS = \
|
INTERNAL_CFLAGS = \
|
||||||
|
-O$(OPT_LEVEL) \
|
||||||
-std=gnu99 \
|
-std=gnu99 \
|
||||||
-ffreestanding \
|
-ffreestanding \
|
||||||
-fno-pic \
|
-flto \
|
||||||
-mno-80387 \
|
-mno-80387 \
|
||||||
-mno-mmx \
|
-mno-mmx \
|
||||||
-mno-sse \
|
-mno-sse \
|
||||||
-mno-sse2 \
|
-mno-sse2 \
|
||||||
-fno-stack-protector \
|
|
||||||
-I. \
|
-I. \
|
||||||
-Wno-address-of-packed-member
|
-Wno-address-of-packed-member
|
||||||
|
|
||||||
LDFLAGS = -flto -Os
|
|
||||||
|
|
||||||
INTERNAL_LDFLAGS = \
|
INTERNAL_LDFLAGS = \
|
||||||
|
-static \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-no-pie \
|
-Tlinker.ld \
|
||||||
-lgcc \
|
-no-pie
|
||||||
-static-libgcc \
|
|
||||||
-Tlinker.ld
|
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
C_FILES := $(shell find ./ -type f -name '*.c' | sort)
|
C_FILES := $(shell find ./ -type f -name '*.c' | sort)
|
||||||
ASM_FILES := $(shell find ./ -type f -name '*.asm' | grep -v bootsect | sort)
|
ASM_FILES := $(shell find ./ -type f -name '*.asm' | grep -v bootsect | sort)
|
||||||
OBJ := $(C_FILES:.c=.o) $(ASM_FILES:.asm=.o)
|
ASM_OBJ := $(ASM_FILES:.asm=.o)
|
||||||
|
BC := $(C_FILES:.c=.bc)
|
||||||
|
|
||||||
all: limine.bin
|
all: limine.bin
|
||||||
|
|
||||||
limine.bin: $(OBJ)
|
limine.bin: libgcc.a $(BC) $(ASM_OBJ)
|
||||||
$(LD) $(OBJ) $(LDFLAGS) $(INTERNAL_LDFLAGS) -o stage2.bin
|
llvm-link $(BC) -o bundle.bc
|
||||||
|
opt --O$(OPT_LEVEL) bundle.bc -o optimised_bundle.bc
|
||||||
|
clang --target=i386-elf -O$(OPT_LEVEL) -c optimised_bundle.bc -o optimised_bundle.o
|
||||||
|
ld.lld optimised_bundle.o $(ASM_OBJ) libgcc.a $(INTERNAL_LDFLAGS) -o stage2.elf
|
||||||
|
llvm-objcopy -O binary stage2.elf stage2.bin
|
||||||
cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
|
cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
|
||||||
|
|
||||||
%.o: %.c
|
libgcc.a:
|
||||||
$(CC) $(CFLAGS) $(INTERNAL_CFLAGS) -c $< -o $@
|
curl https://mirror.netcologne.de/archlinux/core/os/x86_64/gcc-10.2.0-2-x86_64.pkg.tar.zst | \
|
||||||
|
tar -I zstd -xv --strip-components=6 --occurrence=1 usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/32/libgcc.a
|
||||||
|
|
||||||
|
%.bc: %.c
|
||||||
|
clang --target=i386-elf $(CFLAGS) $(INTERNAL_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
%.o: %.asm
|
%.o: %.asm
|
||||||
nasm $< -f elf32 -o $@
|
nasm $< -f elf32 -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJ)
|
rm -f limine.bin $(ASM_OBJ) $(BC)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
OUTPUT_FORMAT(binary)
|
OUTPUT_FORMAT(elf32-i386)
|
||||||
ENTRY(main)
|
ENTRY(main)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
ASM_BASIC(
|
ASM_BASIC(
|
||||||
".section .entry\n\t"
|
".section .entry\n\t"
|
||||||
|
|
||||||
|
"cld\n\t"
|
||||||
|
|
||||||
// Zero out .bss
|
// Zero out .bss
|
||||||
"xor al, al\n\t"
|
"xor al, al\n\t"
|
||||||
"mov edi, OFFSET bss_begin\n\t"
|
"mov edi, OFFSET bss_begin\n\t"
|
||||||
@ -10,7 +12,8 @@ ASM_BASIC(
|
|||||||
"sub ecx, OFFSET bss_begin\n\t"
|
"sub ecx, OFFSET bss_begin\n\t"
|
||||||
"rep stosb\n\t"
|
"rep stosb\n\t"
|
||||||
|
|
||||||
"jmp main\n\t"
|
"mov ebx, OFFSET main\n\t"
|
||||||
|
"jmp ebx\n\t"
|
||||||
);
|
);
|
||||||
|
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
3
toolchain/.gitignore
vendored
3
toolchain/.gitignore
vendored
@ -1,3 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
||||||
!make_toolchain.sh
|
|
@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
PREFIX="$(pwd)"
|
|
||||||
TARGET=i386-elf
|
|
||||||
BINUTILSVERSION=2.35
|
|
||||||
GCCVERSION=10.2.0
|
|
||||||
|
|
||||||
if [ -z "$MAKEFLAGS" ]; then
|
|
||||||
MAKEFLAGS="$1"
|
|
||||||
fi
|
|
||||||
export MAKEFLAGS
|
|
||||||
|
|
||||||
export PATH="$PREFIX/bin:$PATH"
|
|
||||||
|
|
||||||
if [ -x "$(command -v gmake)" ]; then
|
|
||||||
mkdir -p "$PREFIX/bin"
|
|
||||||
cat <<EOF >"$PREFIX/bin/make"
|
|
||||||
#!/usr/bin/env sh
|
|
||||||
gmake "\$@"
|
|
||||||
EOF
|
|
||||||
chmod +x "$PREFIX/bin/make"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
if [ ! -f binutils-$BINUTILSVERSION.tar.gz ]; then
|
|
||||||
wget -4 https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILSVERSION.tar.gz # Force IPv4 otherwise wget hangs
|
|
||||||
fi
|
|
||||||
if [ ! -f gcc-$GCCVERSION.tar.gz ]; then
|
|
||||||
wget -4 https://ftp.gnu.org/gnu/gcc/gcc-$GCCVERSION/gcc-$GCCVERSION.tar.gz # Same as above
|
|
||||||
fi
|
|
||||||
|
|
||||||
tar -xf binutils-$BINUTILSVERSION.tar.gz
|
|
||||||
tar -xf gcc-$GCCVERSION.tar.gz
|
|
||||||
|
|
||||||
rm -rf build-gcc build-binutils
|
|
||||||
|
|
||||||
mkdir build-binutils
|
|
||||||
cd build-binutils
|
|
||||||
../binutils-$BINUTILSVERSION/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
cd gcc-$GCCVERSION
|
|
||||||
contrib/download_prerequisites
|
|
||||||
cd ..
|
|
||||||
mkdir build-gcc
|
|
||||||
cd build-gcc
|
|
||||||
../gcc-$GCCVERSION/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers
|
|
||||||
make all-gcc
|
|
||||||
make all-target-libgcc
|
|
||||||
make install-gcc
|
|
||||||
make install-target-libgcc
|
|
Loading…
Reference in New Issue
Block a user