limine-install: Overhaul

This commit is contained in:
mintsuki 2022-01-27 12:53:40 +01:00
parent 9fc15b377a
commit 55166fda2f
5 changed files with 85 additions and 51 deletions

1
.gitignore vendored
View File

@ -33,3 +33,4 @@ stage23-uefi32
stage23-uefi64 stage23-uefi64
decompressor-build decompressor-build
stage1.stamp stage1.stamp
incbin

View File

@ -196,15 +196,30 @@ override STAGE1_FILES := $(shell find '$(call SHESCAPE,$(SRCDIR))/stage1' -type
.PHONY: all .PHONY: all
all: limine-uefi limine-bios all: limine-uefi limine-bios
$(call MKESCAPE,$(BUILDDIR))/incbin/incbin: $(call MKESCAPE,$(SRCDIR))/incbin/incbin.c
mkdir -p '$(call SHESCAPE,$(BUILDDIR))/incbin'
$(CC) $(CFLAGS) '$(call SHESCAPE,$(SRCDIR))/incbin/incbin.c' -o '$(call SHESCAPE,$(BUILDDIR))/incbin/incbin'
.PHONY: limine-hdd.h
limine-hdd.h: $(call MKESCAPE,$(BINDIR))/limine-hdd.h
$(call MKESCAPE,$(BINDIR))/incbin.h: $(call MKESCAPE,$(SRCDIR))/incbin/incbin.h
cp '$(call SHESCAPE,$(SRCDIR))/incbin/incbin.h' '$(call SHESCAPE,$(BINDIR))/incbin.h'
$(call MKESCAPE,$(BINDIR))/limine-hdd.h: $(call MKESCAPE,$(BINDIR))/incbin.h $(call MKESCAPE,$(BUILDDIR))/incbin/incbin $(call MKESCAPE,$(BINDIR))/limine-hdd.bin
cd '$(call SHESCAPE,$(BINDIR))' && \
'$(call SHESCAPE,$(BUILDDIR))/incbin/incbin' -p _binary_ -Ssnake limine-install.c -o limine-hdd.h
.PHONY: limine-install .PHONY: limine-install
limine-install: limine-install:
mkdir -p '$(call SHESCAPE,$(BINDIR))' mkdir -p '$(call SHESCAPE,$(BINDIR))'
cp '$(call SHESCAPE,$(SRCDIR))/limine-install/'* '$(call SHESCAPE,$(SRCDIR))/limine-install/.gitignore' '$(call SHESCAPE,$(BINDIR))/' cp '$(call SHESCAPE,$(SRCDIR))/limine-install/'* '$(call SHESCAPE,$(SRCDIR))/limine-install/.gitignore' '$(call SHESCAPE,$(BINDIR))/'
$(MAKE) limine-hdd.h
$(MAKE) -C '$(call SHESCAPE,$(BINDIR))' $(MAKE) -C '$(call SHESCAPE,$(BINDIR))'
.PHONY: clean .PHONY: clean
clean: limine-bios-clean limine-uefi32-clean limine-uefi64-clean clean: limine-bios-clean limine-uefi32-clean limine-uefi64-clean
rm -rf '$(call SHESCAPE,$(BINDIR))' '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp' rm -rf '$(call SHESCAPE,$(BINDIR))' '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp' '$(call SHESCAPE,$(BUILDDIR))/incbin'
.PHONY: install-data .PHONY: install-data
install-data: install-data:

View File

@ -11,6 +11,11 @@ cd "$srcdir"
[ -d stivale ] || git clone https://github.com/stivale/stivale.git [ -d stivale ] || git clone https://github.com/stivale/stivale.git
[ -d reduced-gnu-efi ] || git clone https://github.com/limine-bootloader/reduced-gnu-efi.git [ -d reduced-gnu-efi ] || git clone https://github.com/limine-bootloader/reduced-gnu-efi.git
[ -d incbin ] || (
git clone https://github.com/graphitemaster/incbin.git
cd incbin
git checkout 6e576cae5ab5810f25e2631f2e0b80cbe7dc8cbf
)
automake --add-missing --copy || true automake --add-missing --copy || true
autoconf autoconf

View File

@ -9,10 +9,8 @@ CFLAGS ?= -O2 -pipe -Wall -Wextra
.PHONY: all .PHONY: all
all: limine-install all: limine-install
.PHONY: install .PHONY: install-data
install: all install-data: all
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin'
$(INSTALL) -s limine-install '$(DESTDIR)$(PREFIX)/bin/'
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/share' $(INSTALL) -d '$(DESTDIR)$(PREFIX)/share'
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/share/limine' $(INSTALL) -d '$(DESTDIR)$(PREFIX)/share/limine'
$(INSTALL) -m 644 limine.sys '$(DESTDIR)$(PREFIX)/share/limine/' $(INSTALL) -m 644 limine.sys '$(DESTDIR)$(PREFIX)/share/limine/'
@ -22,9 +20,19 @@ install: all
$(INSTALL) -m 644 BOOTX64.EFI '$(DESTDIR)$(PREFIX)/share/limine/' $(INSTALL) -m 644 BOOTX64.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
$(INSTALL) -m 644 BOOTIA32.EFI '$(DESTDIR)$(PREFIX)/share/limine/' $(INSTALL) -m 644 BOOTIA32.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
.PHONY: install
install: install-data
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin'
$(INSTALL) limine-install '$(DESTDIR)$(PREFIX)/bin/'
.PHONY: install-strip
install-strip: install-data
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin'
$(INSTALL) -s limine-install '$(DESTDIR)$(PREFIX)/bin/'
.PHONY: clean .PHONY: clean
clean: clean:
rm -f limine-install limine-install.exe rm -f limine-install limine-install.exe
limine-install: limine-install.c inc.S limine-hdd.bin limine-install: limine-install.c
$(CC) $(CFLAGS) -std=c11 limine-install.c inc.S -o $@ $(CC) $(CFLAGS) -std=c11 limine-install.c -o $@

View File

@ -1,4 +1,12 @@
#undef IS_WINDOWS
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#define IS_WINDOWS 1
#endif
#ifndef IS_WINDOWS
#define _POSIX_C_SOURCE 200112L
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -7,12 +15,14 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <fcntl.h>
#include <unistd.h>
#ifndef O_BINARY static inline int seek_(FILE *stream, int64_t offset, int whence) {
#define O_BINARY 0 #ifdef IS_WINDOWS
return _fseeki64(stream, offset, whence);
#else
return fseeko(stream, offset, whence);
#endif #endif
}
#define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b)) #define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
@ -38,7 +48,7 @@ struct gpt_table_header {
uint32_t number_of_partition_entries; uint32_t number_of_partition_entries;
uint32_t size_of_partition_entry; uint32_t size_of_partition_entry;
uint32_t partition_entry_array_crc32; uint32_t partition_entry_array_crc32;
} __attribute__((packed)); };
struct gpt_entry { struct gpt_entry {
uint64_t partition_type_guid[2]; uint64_t partition_type_guid[2];
@ -51,7 +61,7 @@ struct gpt_entry {
uint64_t attributes; uint64_t attributes;
uint16_t partition_name[36]; uint16_t partition_name[36];
} __attribute__((packed)); };
// This table from https://web.mit.edu/freebsd/head/sys/libkern/crc32.c // This table from https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
static const uint32_t crc32_table[] = { static const uint32_t crc32_table[] = {
@ -118,7 +128,7 @@ static enum {
} cache_state; } cache_state;
static uint64_t cached_block; static uint64_t cached_block;
static uint8_t *cache = NULL; static uint8_t *cache = NULL;
static int device = -1; static FILE *device = NULL;
static size_t block_size; static size_t block_size;
static bool device_init(void) { static bool device_init(void) {
@ -132,24 +142,22 @@ static bool device_init(void) {
} }
cache = tmp; cache = tmp;
if (lseek(device, 0, SEEK_SET) == (off_t)-1) { if (seek_(device, 0, SEEK_SET) == -1) {
perror("ERROR"); perror("ERROR");
return false; return false;
} }
ssize_t ret = read(device, cache, guesses[i]); size_t ret = fread(cache, guesses[i], 1, device);
if (ret == -1) { if (ret != 1) {
perror("ERROR"); continue;
return false;
} }
block_size = ret;
if (block_size == guesses[i]) { block_size = guesses[i];
fprintf(stderr, "Physical block size of %zu bytes.\n", block_size);
cache_state = CACHE_CLEAN; fprintf(stderr, "Physical block size of %zu bytes.\n", block_size);
cached_block = 0;
return true; cache_state = CACHE_CLEAN;
} cached_block = 0;
return true;
} }
fprintf(stderr, "ERROR: Couldn't determine block size of device.\n"); fprintf(stderr, "ERROR: Couldn't determine block size of device.\n");
@ -160,20 +168,16 @@ static bool device_flush_cache(void) {
if (cache_state == CACHE_CLEAN) if (cache_state == CACHE_CLEAN)
return true; return true;
if (lseek(device, cached_block * block_size, SEEK_SET) == (off_t)-1) { if (seek_(device, cached_block * block_size, SEEK_SET) == -1) {
perror("ERROR"); perror("ERROR");
return false; return false;
} }
ssize_t ret = write(device, cache, block_size); size_t ret = fwrite(cache, block_size, 1, device);
if (ret == -1) { if (ret != 1) {
perror("ERROR"); perror("ERROR");
return false; return false;
} }
if ((size_t)ret != block_size) {
fprintf(stderr, "ERROR: Wrote back less bytes than cache size.\n");
return false;
}
cache_state = CACHE_CLEAN; cache_state = CACHE_CLEAN;
return true; return true;
@ -188,20 +192,16 @@ static bool device_cache_block(uint64_t block) {
return false; return false;
} }
if (lseek(device, block * block_size, SEEK_SET) == (off_t)-1) { if (seek_(device, block * block_size, SEEK_SET) == -1) {
perror("ERROR"); perror("ERROR");
return false; return false;
} }
ssize_t ret = read(device, cache, block_size); size_t ret = fread(cache, block_size, 1, device);
if (ret == -1) { if (ret != 1) {
perror("ERROR"); perror("ERROR");
return false; return false;
} }
if ((size_t)ret != block_size) {
fprintf(stderr, "ERROR: Read back less bytes than cache size.\n");
return false;
}
cached_block = block; cached_block = block;
@ -267,20 +267,25 @@ static bool _device_write(const void *_buffer, uint64_t loc, size_t count) {
goto cleanup; \ goto cleanup; \
} while (0) } while (0)
extern uint8_t _binary_limine_hdd_bin_start[], _binary_limine_hdd_bin_end[]; /* dummy incbin call so incbin generates the header
INCBIN(limine_hdd_bin, "limine-hdd.bin");
*/
#include "limine-hdd.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int ok = 1; int ok = 1;
int force_mbr = 0; int force_mbr = 0;
uint8_t *bootloader_img = _binary_limine_hdd_bin_start; uint8_t *bootloader_img = (uint8_t *)_binary_limine_hdd_bin_data;
size_t bootloader_file_size = size_t bootloader_file_size = (size_t)_binary_limine_hdd_bin_size;
(size_t)_binary_limine_hdd_bin_end - (size_t)_binary_limine_hdd_bin_start;
uint8_t orig_mbr[70], timestamp[6]; uint8_t orig_mbr[70], timestamp[6];
#ifndef IS_WINDOWS
if (sizeof(off_t) != 8) { if (sizeof(off_t) != 8) {
fprintf(stderr, "ERROR: off_t type is not 64-bit.\n"); fprintf(stderr, "ERROR: off_t type is not 64-bit.\n");
goto cleanup; goto cleanup;
} }
#endif
if (argc < 2) { if (argc < 2) {
printf("Usage: %s <device> [GPT partition index]\n", argv[0]); printf("Usage: %s <device> [GPT partition index]\n", argv[0]);
@ -293,8 +298,8 @@ int main(int argc, char *argv[]) {
} }
} }
device = open(argv[1], O_RDWR | O_BINARY); device = fopen(argv[1], "r+b");
if (device == -1) { if (device == NULL) {
perror("ERROR"); perror("ERROR");
goto cleanup; goto cleanup;
} }
@ -491,8 +496,8 @@ int main(int argc, char *argv[]) {
} else { } else {
fprintf(stderr, "GPT partition NOT specified. Attempting GPT embedding.\n"); fprintf(stderr, "GPT partition NOT specified. Attempting GPT embedding.\n");
ssize_t max_partition_entry_used = -1; int64_t max_partition_entry_used = -1;
for (ssize_t i = 0; i < (ssize_t)gpt_header.number_of_partition_entries; i++) { for (int64_t i = 0; i < (int64_t)gpt_header.number_of_partition_entries; i++) {
struct gpt_entry gpt_entry; struct gpt_entry gpt_entry;
device_read(&gpt_entry, device_read(&gpt_entry,
(gpt_header.partition_entry_lba * lb_size) (gpt_header.partition_entry_lba * lb_size)
@ -520,7 +525,7 @@ int main(int argc, char *argv[]) {
size_t new_partition_entry_count = size_t new_partition_entry_count =
new_partition_array_lba_size * partition_entries_per_lb; new_partition_array_lba_size * partition_entries_per_lb;
if ((ssize_t)new_partition_entry_count <= max_partition_entry_used) { if ((int64_t)new_partition_entry_count <= max_partition_entry_used) {
fprintf(stderr, "ERROR: Cannot embed because there are too many used partition entries.\n"); fprintf(stderr, "ERROR: Cannot embed because there are too many used partition entries.\n");
goto cleanup; goto cleanup;
} }
@ -623,8 +628,8 @@ int main(int argc, char *argv[]) {
cleanup: cleanup:
if (cache) if (cache)
free(cache); free(cache);
if (device != -1) if (device != NULL)
close(device); fclose(device);
return ok; return ok;
} }