diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2021-03-23 08:50:34 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-03-25 13:25:51 +0100 |
commit | d44fdb7d9b8527c758deefc4262fedd6a121ffc6 (patch) | |
tree | 6d8f2c3218d1c745bda59eb6a9120c7ea6dadf3b /scripts | |
parent | 41fd0332e797c0a3c6a0d9cbf14e7528f2a3209d (diff) | |
download | barebox-d44fdb7d9b8527c758deefc4262fedd6a121ffc6.tar.gz barebox-d44fdb7d9b8527c758deefc4262fedd6a121ffc6.tar.xz |
x86: drop legacy (PC BIOS) boot in favor of EFI
The 16-bit port has experienced bitrot and failed to compile with more
recent linkers for at least a year. Fixing the linker error is insufficient
to restore a barebox that can boot to shell. This continued breakage likely
means that there are no users interested in updating. As new x86 projects
should be using MACH_EFI_GENERIC anyway, retire support for 16-bit legacy
boot (MACH_X86_GENERIC).
Acked-by: Juergen Borleis <jbe@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile | 1 | ||||
-rw-r--r-- | scripts/setupmbr/.gitignore | 1 | ||||
-rw-r--r-- | scripts/setupmbr/Makefile | 3 | ||||
-rw-r--r-- | scripts/setupmbr/arch.h | 55 | ||||
-rw-r--r-- | scripts/setupmbr/setupmbr.c | 545 |
5 files changed, 0 insertions, 605 deletions
diff --git a/scripts/Makefile b/scripts/Makefile index 4dc70815b7..2d322fd1c9 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -43,7 +43,6 @@ userccflags += -I $(srctree)/$(src)/include subdir-y += mod subdir-y += imx -subdir-$(CONFIG_X86) += setupmbr subdir-$(CONFIG_DTC) += dtc subdir-$(CONFIG_ARCH_TEGRA) += tegra diff --git a/scripts/setupmbr/.gitignore b/scripts/setupmbr/.gitignore deleted file mode 100644 index a7301f9111..0000000000 --- a/scripts/setupmbr/.gitignore +++ /dev/null @@ -1 +0,0 @@ -setupmbr diff --git a/scripts/setupmbr/Makefile b/scripts/setupmbr/Makefile deleted file mode 100644 index 6e33d15362..0000000000 --- a/scripts/setupmbr/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -HOST_EXTRACFLAGS=-I$(srctree) - -hostprogs-always-y += setupmbr diff --git a/scripts/setupmbr/arch.h b/scripts/setupmbr/arch.h deleted file mode 100644 index a720dfe95e..0000000000 --- a/scripts/setupmbr/arch.h +++ /dev/null @@ -1,55 +0,0 @@ - -/* we need the one from the host */ -#include <endian.h> -#include <stdint.h> - -/* Byte-orders. */ -#define swap16(x) \ -({ \ - uint16_t _x = (x); \ - (uint16_t) ((_x << 8) | (_x >> 8)); \ -}) - -#define swap32(x) \ -({ \ - uint32_t _x = (x); \ - (uint32_t) ((_x << 24) \ - | ((_x & (uint32_t) 0xFF00UL) << 8) \ - | ((_x & (uint32_t) 0xFF0000UL) >> 8) \ - | (_x >> 24)); \ -}) - -#define swap64(x) \ -({ \ - uint64_t _x = (x); \ - (uint64_t) ((_x << 56) \ - | ((_x & (uint64_t) 0xFF00ULL) << 40) \ - | ((_x & (uint64_t) 0xFF0000ULL) << 24) \ - | ((_x & (uint64_t) 0xFF000000ULL) << 8) \ - | ((_x & (uint64_t) 0xFF00000000ULL) >> 8) \ - | ((_x & (uint64_t) 0xFF0000000000ULL) >> 24) \ - | ((_x & (uint64_t) 0xFF000000000000ULL) >> 40) \ - | (_x >> 56)); \ -}) - -#if __BYTE_ORDER == __BIG_ENDIAN - -/* Our target is a ia32 machine, always little endian */ - -# define host2target_16(x) swap16(x) -# define host2target_32(x) swap32(x) -# define host2target_64(x) swap64(x) -# define target2host_16(x) swap16(x) -# define target2host_32(x) swap32(x) -# define target2host_64(x) swap64(x) - -#else - -# define host2target_16(x) (x) -# define host2target_32(x) (x) -# define host2target_64(x) (x) -# define target2host_16(x) (x) -# define target2host_32(x) (x) -# define target2host_64(x) (x) - -#endif diff --git a/scripts/setupmbr/setupmbr.c b/scripts/setupmbr/setupmbr.c deleted file mode 100644 index 38af550809..0000000000 --- a/scripts/setupmbr/setupmbr.c +++ /dev/null @@ -1,545 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -// SPDX-FileCopyrightText: 2009 Juergen Beisert, Pengutronix - -/** - * @file - * @brief Write the barebox binary to the MBR and the following disk sectors - * - * Also patch dedicated locations in the image to make it work at runtime - * - * Current restrictions are: - * - only installs into MBR and the sectors after it - * - tested only with QEMU - * - and maybe some others - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <assert.h> - -/* include the info from this barebox release */ -#include "../../include/generated/utsrelease.h" -#include "../../arch/x86/mach-i386/include/mach/barebox.lds.h" - -/** define to disable integrity tests and debug messages */ -#define NDEBUG - -/* some infos about our target architecture */ -#include "arch.h" - -/** - * "Disk Address Packet Structure" to be used when calling int13, - * function 0x42 - * - * @note All entries are in target endianess - */ -struct DAPS -{ - uint8_t size; /**< size of this data set, 0 marks it as invalid */ - uint8_t res1; /**< always 0 */ - int8_t count; /**< number of sectors 0...127 to handle */ - uint8_t res2; /**< always 0 */ - uint16_t offset; /**< store address: offset */ - uint16_t segment; /**< store address: segment */ - uint64_t lba; /**< start sector number in LBA */ -} __attribute__ ((packed)); - -/** - * Description of one partition table entry (D*S type) - * - * @note All entries are in target endianess - */ -struct partition_entry { - uint8_t boot_indicator; - uint8_t chs_begin[3]; - uint8_t type; - uint8_t chs_end[3]; - uint32_t partition_start; /* LE */ - uint32_t partition_size; /* LE */ -} __attribute__ ((packed)); - -#ifndef NDEBUG -static void debugout(const struct DAPS *entry, int supress_entry) -{ - if (supress_entry) - printf("DAPS entry: "); - else - printf("DAPS entry % 3u: ", ((unsigned)entry & ( SECTOR_SIZE - 1)) / sizeof(struct DAPS)); - - printf("Size: % 2u, Count: % 3d, Offset: 0x%04hX, Segment: 0x%04hX, LBA: %llu\n", - entry->size, entry->count, - target2host_16(entry->offset), target2host_16(entry->segment), - target2host_64(entry->lba)); -} -#else -# define debugout(x,y) (__ASSERT_VOID_CAST(0)) -#endif - -/** - * Fill *one* DAPS - * @param sector The DAPS to fill - * @param count Sector count - * @param offset Realmode offset in the segment - * @param segment Real mode segment - * @param lba LBA of the first sector to read - * @return 0 on success - */ -static int fill_daps(struct DAPS *sector, unsigned count, unsigned offset, unsigned segment, uint64_t lba) -{ - assert(sector != NULL); - assert(count < 128); - assert(offset < 0x10000); - assert(segment < 0x10000); - - sector->size = sizeof(struct DAPS); - sector->res1 = 0; - sector->count = (int8_t)count; - sector->res2 = 0; - sector->offset = host2target_16(offset); - sector->segment = host2target_16(segment); - sector->lba = host2target_64(lba); - - return 0; -} - -/** - * Mark a DAPS invalid to let the boot loader code stop at this entry. - * @param sector The DAPS to be marked as invalid - * - * Marking as invalid must be done in accordance to the detection method - * the assembler routine in the boot loader uses: - * The current code tests for zero in the first two bytes of the DAPS. - */ -static void invalidate_daps(struct DAPS *sector) -{ - sector->size = MARK_DAPS_INVALID; - sector->res1 = 0; -} - -/** - * Create the indirect sector with the DAPS entries - * @param daps_table Where to store the entries - * @param size Size of the whole image in bytes - * @param pers_sector_count Count of sectors to skip after MBR for the persistent environment storage - * @return 0 on success - * - * This routine calculates the DAPS entries for the case the whole - * barebox images fits into the MBR itself and the sectors after it. - * This means the start of the first partition must keep enough sectors - * unused. - * It also skips 'pers_sector_count' sectors after the MBR for special - * usage if given. - */ -static int barebox_linear_image(struct DAPS *daps_table, off_t size, long pers_sector_count) -{ - unsigned offset = LOAD_AREA, next_offset; - unsigned segment = LOAD_SEGMENT; - unsigned chunk_size, i = 0; - uint64_t lba = 2 + pers_sector_count; - int rc; - - /* - * We can load up to 127 sectors in one chunk. What a bad number... - * So, we will load in chunks of 32 kiB. - */ - - /* at runtime two sectors from the image are already loaded: MBR and indirect */ - size -= 2 * SECTOR_SIZE; - /* and now round up to multiple of sector size */ - size = (size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); - - /* - * The largest image we can load with this method is: - * (SECTOR_SIZE / sizeof(DAPS) - 1) * 32 kiB - * For a 512 byte sector and a 16 byte DAPS: - * (512 / 16 - 1) * 32 kiB = 992 kiB - * Note: '- 1' to consider one entry is required to pad to a 32 kiB boundary - */ - - if (size >= (SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32 * 1024) { - fprintf(stderr, "Image too large to boot. Max size is %zu kiB, image size is %lu kiB\n", - (SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32, size / 1024); - return -1; - } - - if (size > 32 * 1024) { - /* first fill up until the next 32 k boundary */ - next_offset = (offset + 32 * 1024 -1) & ~0x7fff; - chunk_size = next_offset - offset; - if (chunk_size & (SECTOR_SIZE-1)) { - fprintf(stderr, "Unable to pad from %X to %X in multiple of sectors\n", offset, next_offset); - return -1; - } - - rc = fill_daps(&daps_table[i], chunk_size / SECTOR_SIZE, offset, segment, lba); - if (rc != 0) - return -1; - debugout(&daps_table[i], 0); - - /* calculate values to enter the loop for the other entries */ - size -= chunk_size; - i++; - lba += chunk_size / SECTOR_SIZE; - offset += chunk_size; - if (offset >= 0x10000) { - segment += 4096; - offset = 0; - } - - /* - * Now load the remaining image part in 32 kiB chunks - */ - while (size) { - if (size >= 32 * 1024 ) { - if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) { - fprintf(stderr, "Internal tool error: Too many DAPS entries!\n"); - return -1; - } - rc = fill_daps(&daps_table[i], 64, offset, segment, lba); - if (rc != 0) - return -1; - debugout(&daps_table[i], 0); - - size -= 32 * 1024; - lba += 64; - offset += 32 * 1024; - if (offset >= 0x10000) { - segment += 4096; - offset = 0; - } - i++; - } else { - if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) { - fprintf(stderr, "Internal tool error: Too many DAPS entries!\n"); - return -1; - } - rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba); - if (rc != 0) - return -1; - debugout(&daps_table[i], 0); - size = 0; /* finished */ - i++; - } - }; - } else { - /* less than 32 kiB. Very small image... */ - rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba); - if (rc != 0) - return -1; - debugout(&daps_table[i], 0); - i++; - } - - /* - * Do not mark an entry as invalid if the buffer is full. The - * boot code stops if all entries of a buffer are read. - */ - if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) - return 0; - - /* mark the last DAPS invalid */ - invalidate_daps(&daps_table[i]); - debugout(&daps_table[i], 0); - - return 0; -} - -/** - * Do some simple sanity checks if this sector could be an MBR - * @param sector Sector with data to check - * @param size Size of the buffer - * @return 0 if successfull - */ -static int check_for_valid_mbr(const uint8_t *sector, off_t size) -{ - if (size < SECTOR_SIZE) { - fprintf(stderr, "MBR too small to be valid\n"); - return -1; - } - - if ((sector[OFFSET_OF_SIGNATURE] != 0x55) || - (sector[OFFSET_OF_SIGNATURE + 1] != 0xAA)) { - fprintf(stderr, "No MBR signature found\n"); - return -1; - } - - /* FIXME: try to check if there is a valid partition table */ - return 0; -} - -/** - * Check space between start of the image and the start of the first partition - * @param hd_image HD image to examine - * @param size Size of the barebox image - * @return 0 on success, -1 if the barebox image is too large - */ -static int check_for_space(const void *hd_image, off_t size) -{ - struct partition_entry *partition; - uint8_t *mbr_disk_sector = (uint8_t*)hd_image; - off_t spare_sector_count; - - assert(hd_image != NULL); - assert(size > 0); - - if (check_for_valid_mbr(hd_image, size) != 0) - return -1; - - /* where to read */ - partition = (struct partition_entry*) &mbr_disk_sector[OFFSET_OF_PARTITION_TABLE]; - - /* TODO describes the first entry always the first partition? */ - spare_sector_count = target2host_32(partition->partition_start); - -#ifdef DEBUG - printf("Debug: Required free sectors for barebox prior first partition: %lu, hd image provides: %lu\n", - (size + SECTOR_SIZE - 1) / SECTOR_SIZE, spare_sector_count); -#endif - spare_sector_count *= SECTOR_SIZE; - if (spare_sector_count < size) { - fprintf(stderr, "Not enough space after MBR to store barebox\n"); - fprintf(stderr, "Move begin of the first partition beyond sector %lu\n", (size + SECTOR_SIZE - 1) / SECTOR_SIZE); - return -1; - } - - return 0; -} - -/** - * Setup the persistent environment storage information - * @param patch_area Where to patch - * @param pers_sector_start Start sector of the persistent environment storage - * @param pers_sector_count Count of sectors for the persistent environment storage - * @return 0 on success - */ -static int store_pers_env_info(void *patch_area, uint64_t pers_sector_start, long pers_sector_count) -{ - uint64_t *start_lba = (uint64_t*)(patch_area + PATCH_AREA_PERS_START); - uint16_t *count_lba = (uint16_t*)(patch_area + PATCH_AREA_PERS_SIZE); - - assert(patch_area != NULL); - assert(pers_sector_count >= 0); - - if (pers_sector_count == 0) { - *count_lba = host2target_16(PATCH_AREA_PERS_SIZE_UNUSED); - return 0; - } - - *start_lba = host2target_64(pers_sector_start); - *count_lba = host2target_16(pers_sector_count); - - return 0; -} - -/** - * Prepare the MBR and indirect sector for runtime - * @param fd_barebox barebox image to use - * @param fd_hd Hard disk image to prepare - * @param pers_sector_count Count of sectors to skip after MBR for the persistent environment storage - * @return 0 on success - * - * This routine expects a prepared hard disk image file with a partition table - * in its first sector. This method only is currently supported. - */ -static int barebox_overlay_mbr(int fd_barebox, int fd_hd, long pers_sector_count) -{ - const void *barebox_image; - void *hd_image; - int rc; - struct stat sb; - struct DAPS *embed; /* part of the MBR */ - struct DAPS *indirect; /* sector with indirect DAPS */ - off_t required_size; - - if (fstat(fd_barebox, &sb) == -1) { - perror("fstat"); - return -1; - } - - /* the barebox image won't be touched */ - barebox_image = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd_barebox, 0); - if (barebox_image == MAP_FAILED) { - perror("mmap"); - return -1; - } - - rc = check_for_valid_mbr(barebox_image, sb.st_size); - if (rc != 0) { - fprintf(stderr, "barebox image seems not valid: Bad MBR signature\n"); - goto on_error_hd; - } - - /* - * the persistent environment storage is in front of the main - * barebox image. To handle both, we need more space in front of the - * the first partition. - */ - required_size = sb.st_size + pers_sector_count * SECTOR_SIZE; - - /* the hd image will be modified */ - hd_image = mmap(NULL, required_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd_hd, 0); - if (hd_image == MAP_FAILED) { - perror("mmap"); - rc = -1; - goto on_error_hd; - } - - /* check for space */ - rc = check_for_space(hd_image, required_size); - if (rc != 0) - goto on_error_space; - - /* embed barebox's boot code into the disk drive image */ - memcpy(hd_image, barebox_image, OFFSET_OF_PARTITION_TABLE); - - /* - * embed the barebox main image into the disk drive image, - * but keep the persistent environment storage untouched - * (if defined), e.g. store the main image behind this special area. - */ - memcpy(hd_image + ((pers_sector_count + 1) * SECTOR_SIZE), - barebox_image + SECTOR_SIZE, sb.st_size - SECTOR_SIZE); - - /* now, prepare this hard disk image for BIOS based booting */ - embed = hd_image + PATCH_AREA; - indirect = hd_image + ((pers_sector_count + 1) * SECTOR_SIZE); - - /* - * Fill the embedded DAPS to let the basic boot code find the - * indirect sector at runtime - */ -#ifdef DEBUG - printf("Debug: Fill in embedded DAPS\n"); -#endif - rc = fill_daps(embed, 1, INDIRECT_AREA, INDIRECT_SEGMENT, - 1 + pers_sector_count); - if (rc != 0) - goto on_error_space; - debugout(embed, 1); - -#ifdef DEBUG - printf("Debug: Fill in indirect sector\n"); -#endif - /* - * fill the indirect sector with the remaining DAPS to load the - * whole barebox image at runtime - */ - rc = barebox_linear_image(indirect, sb.st_size, pers_sector_count); - if (rc != 0) - goto on_error_space; - - /* - * TODO: Replace the fixed LBA starting number by a calculated one, - * to support barebox as a chained loader in a different start - * sector than the MBR - */ - rc = store_pers_env_info(embed, 1, pers_sector_count); - if (rc != 0) - goto on_error_space; - -on_error_space: - munmap(hd_image, required_size); - -on_error_hd: - munmap((void*)barebox_image, sb.st_size); - - return rc; -} - -static void print_usage(const char *pname) -{ - printf("%s: Preparing a hard disk image for boot with barebox on x86.\n", pname); - printf("Usage is\n %s [options] -m <barebox image> -d <hd image>\n", pname); - printf(" [options] are:\n -s <count> sector count of the persistent environment storage\n"); - printf(" <barebox image> barebox's boot image file\n"); - printf(" <hd image> HD image to store the barebox image\n"); - printf(" If no '-s <x>' was given, barebox occupies sectors 0 to n, else sector 0 and x+1 to n\n"); -} - -int main(int argc, char *argv[]) -{ - int rc = 0, c; - char *barebox_image_filename = NULL, *hd_image_filename = NULL; - int fd_barebox_image = 0, fd_hd_image = 0; - long barebox_pers_size = -1; - - if (argc == 1) { - print_usage(argv[0]); - exit(0); - } - - /* handle command line options first */ - while (1) { - c = getopt(argc, argv, "m:d:s:hv"); - if (c == -1) - break; - - switch (c) { - case 's': - barebox_pers_size = strtol(optarg, NULL, 0); - break; - case 'm': - barebox_image_filename = strdup(optarg); - break; - case 'd': - hd_image_filename = strdup(optarg); - break; - case 'h': - print_usage(argv[0]); - rc = 0; - goto on_error; - case 'v': - printf("setupmbr for u-boot-v%s\n", UTS_RELEASE); - printf("Send bug reports to 'barebox@lists.infradead.org'\n"); - rc = 0; - goto on_error; - } - } - - if (barebox_image_filename == NULL) { - print_usage(argv[0]); - rc = -1; - goto on_error; - } - - fd_barebox_image = open(barebox_image_filename, O_RDONLY); - if (fd_barebox_image == -1) { - fprintf(stderr, "Cannot open '%s' for reading\n", - barebox_image_filename); - rc = -1; - goto on_error; - } - - fd_hd_image = open(hd_image_filename, O_RDWR); - if (fd_hd_image == -1) { - fprintf(stderr, "Cannot open '%s'\n", hd_image_filename); - rc = -1; - goto on_error; - } - - if (barebox_pers_size < 0) - barebox_pers_size = 0; - - rc = barebox_overlay_mbr(fd_barebox_image, fd_hd_image, barebox_pers_size); - -on_error: - if (fd_barebox_image != -1) - close(fd_barebox_image); - if (fd_hd_image != -1) - close(fd_hd_image); - - if (barebox_image_filename != NULL) - free(barebox_image_filename); - if (hd_image_filename != NULL) - free(hd_image_filename); - - return rc; -} |