Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/boot: Drop CRC-32 checksum and the build tool that generates it

Apart from some sanity checks on the size of setup.bin, the only
remaining task carried out by the arch/x86/boot/tools/build.c build tool
is generating the CRC-32 checksum of the bzImage. This feature was added
in commit

7d6e737c8d2698b6 ("x86: add a crc32 checksum to the kernel image.")

without any motivation (or any commit log text, for that matter). This
checksum is not verified by any known bootloader, and given that

a) the checksum of the entire bzImage is reported by most tools (zlib,
rhash) as 0xffffffff and not 0x0 as documented,

b) the checksum is corrupted when the image is signed for secure boot,
which means that no distro ships x86 images with valid CRCs,

it seems quite unlikely that this checksum is being used, so let's just
drop it, along with the tool that generates it.

Instead, use simple file concatenation and truncation to combine the two
pieces into bzImage, and replace the checks on the size of the setup
block with a couple of ASSERT()s in the linker script.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ian Campbell <ijc@hellion.org.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250307164801.885261-2-ardb+git@google.com

authored by

Ard Biesheuvel and committed by
Ingo Molnar
9c54baab e4516302

+5 -266
-10
Documentation/arch/x86/boot.rst
··· 1038 1038 This field contains maximal allowed type for setup_data and setup_indirect structs. 1039 1039 1040 1040 1041 - The Image Checksum 1042 - ================== 1043 - 1044 - From boot protocol version 2.08 onwards the CRC-32 is calculated over 1045 - the entire file using the characteristic polynomial 0x04C11DB7 and an 1046 - initial remainder of 0xffffffff. The checksum is appended to the 1047 - file; therefore the CRC of the file up to the limit specified in the 1048 - syssize field of the header is always 0. 1049 - 1050 - 1051 1041 The Kernel Command Line 1052 1042 ======================= 1053 1043
+2 -5
arch/x86/boot/Makefile
··· 35 35 setup-y += video-bios.o 36 36 37 37 targets += $(setup-y) 38 - hostprogs := tools/build 39 38 hostprogs += mkcpustr 40 39 41 40 HOST_EXTRACFLAGS += -I$(srctree)/tools/include \ ··· 60 61 $(obj)/bzImage: asflags-y := $(SVGA_MODE) 61 62 62 63 quiet_cmd_image = BUILD $@ 63 - silent_redirect_image = >/dev/null 64 - cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \ 65 - $(obj)/zoffset.h $@ $($(quiet)redirect_image) 64 + cmd_image = cp $< $@; truncate -s %4K $@; cat $(obj)/vmlinux.bin >>$@ 66 65 67 - $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE 66 + $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin FORCE 68 67 $(call if_changed,image) 69 68 @$(kecho) 'Kernel: $@ is ready' ' (#'$(or $(KBUILD_BUILD_VERSION),`cat .version`)')' 70 69
+1 -2
arch/x86/boot/compressed/vmlinux.lds.S
··· 48 48 *(.data) 49 49 *(.data.*) 50 50 51 - /* Add 4 bytes of extra space for a CRC-32 checksum */ 52 - . = ALIGN(. + 4, 0x200); 51 + . = ALIGN(0x200); 53 52 _edata = . ; 54 53 } 55 54 . = ALIGN(L1_CACHE_BYTES);
+2
arch/x86/boot/setup.ld
··· 45 45 46 46 setup_size = ALIGN(ABSOLUTE(.), 4096); 47 47 setup_sects = ABSOLUTE(setup_size / 512); 48 + ASSERT(setup_sects >= 5, "The setup must be at least 5 sectors in size"); 49 + ASSERT(setup_sects <= 64, "The setup must be at most 64 sectors in size"); 48 50 } 49 51 50 52 . = ALIGN(16);
-2
arch/x86/boot/tools/.gitignore
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - build
-247
arch/x86/boot/tools/build.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (C) 1991, 1992 Linus Torvalds 4 - * Copyright (C) 1997 Martin Mares 5 - * Copyright (C) 2007 H. Peter Anvin 6 - */ 7 - 8 - /* 9 - * This file builds a disk-image from three different files: 10 - * 11 - * - setup: 8086 machine code, sets up system parm 12 - * - system: 80386 code for actual system 13 - * - zoffset.h: header with ZO_* defines 14 - * 15 - * It does some checking that all files are of the correct type, and writes 16 - * the result to the specified destination, removing headers and padding to 17 - * the right amount. It also writes some system data to stdout. 18 - */ 19 - 20 - /* 21 - * Changes by tytso to allow root device specification 22 - * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 23 - * Cross compiling fixes by Gertjan van Wingerde, July 1996 24 - * Rewritten by Martin Mares, April 1997 25 - * Substantially overhauled by H. Peter Anvin, April 2007 26 - */ 27 - 28 - #include <stdio.h> 29 - #include <string.h> 30 - #include <stdlib.h> 31 - #include <stdarg.h> 32 - #include <sys/types.h> 33 - #include <sys/stat.h> 34 - #include <unistd.h> 35 - #include <fcntl.h> 36 - #include <sys/mman.h> 37 - #include <tools/le_byteshift.h> 38 - 39 - typedef unsigned char u8; 40 - typedef unsigned short u16; 41 - typedef unsigned int u32; 42 - 43 - /* Minimal number of setup sectors */ 44 - #define SETUP_SECT_MIN 5 45 - #define SETUP_SECT_MAX 64 46 - 47 - /* This must be large enough to hold the entire setup */ 48 - u8 buf[SETUP_SECT_MAX*512]; 49 - 50 - static unsigned long _edata; 51 - 52 - /*----------------------------------------------------------------------*/ 53 - 54 - static const u32 crctab32[] = { 55 - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 56 - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 57 - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 58 - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 59 - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 60 - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 61 - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 62 - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 63 - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 64 - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 65 - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 66 - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 67 - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 68 - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 69 - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 70 - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 71 - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 72 - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 73 - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 74 - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 75 - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 76 - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 77 - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 78 - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 79 - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 80 - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 81 - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 82 - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 83 - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 84 - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 85 - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 86 - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 87 - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 88 - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 89 - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 90 - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 91 - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 92 - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 93 - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 94 - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 95 - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 96 - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 97 - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 98 - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 99 - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 100 - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 101 - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 102 - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 103 - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 104 - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 105 - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 106 - 0x2d02ef8d 107 - }; 108 - 109 - static u32 partial_crc32_one(u8 c, u32 crc) 110 - { 111 - return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); 112 - } 113 - 114 - static u32 partial_crc32(const u8 *s, int len, u32 crc) 115 - { 116 - while (len--) 117 - crc = partial_crc32_one(*s++, crc); 118 - return crc; 119 - } 120 - 121 - static void die(const char * str, ...) 122 - { 123 - va_list args; 124 - va_start(args, str); 125 - vfprintf(stderr, str, args); 126 - va_end(args); 127 - fputc('\n', stderr); 128 - exit(1); 129 - } 130 - 131 - static void usage(void) 132 - { 133 - die("Usage: build setup system zoffset.h image"); 134 - } 135 - 136 - /* 137 - * Parse zoffset.h and find the entry points. We could just #include zoffset.h 138 - * but that would mean tools/build would have to be rebuilt every time. It's 139 - * not as if parsing it is hard... 140 - */ 141 - #define PARSE_ZOFS(p, sym) do { \ 142 - if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \ 143 - sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \ 144 - } while (0) 145 - 146 - static void parse_zoffset(char *fname) 147 - { 148 - FILE *file; 149 - char *p; 150 - int c; 151 - 152 - file = fopen(fname, "r"); 153 - if (!file) 154 - die("Unable to open `%s': %m", fname); 155 - c = fread(buf, 1, sizeof(buf) - 1, file); 156 - if (ferror(file)) 157 - die("read-error on `zoffset.h'"); 158 - fclose(file); 159 - buf[c] = 0; 160 - 161 - p = (char *)buf; 162 - 163 - while (p && *p) { 164 - PARSE_ZOFS(p, _edata); 165 - 166 - p = strchr(p, '\n'); 167 - while (p && (*p == '\r' || *p == '\n')) 168 - p++; 169 - } 170 - } 171 - 172 - int main(int argc, char ** argv) 173 - { 174 - unsigned int i, sz, setup_sectors; 175 - int c; 176 - struct stat sb; 177 - FILE *file, *dest; 178 - int fd; 179 - void *kernel; 180 - u32 crc = 0xffffffffUL; 181 - 182 - if (argc != 5) 183 - usage(); 184 - parse_zoffset(argv[3]); 185 - 186 - dest = fopen(argv[4], "w"); 187 - if (!dest) 188 - die("Unable to write `%s': %m", argv[4]); 189 - 190 - /* Copy the setup code */ 191 - file = fopen(argv[1], "r"); 192 - if (!file) 193 - die("Unable to open `%s': %m", argv[1]); 194 - c = fread(buf, 1, sizeof(buf), file); 195 - if (ferror(file)) 196 - die("read-error on `setup'"); 197 - if (c < 1024) 198 - die("The setup must be at least 1024 bytes"); 199 - if (get_unaligned_le16(&buf[510]) != 0xAA55) 200 - die("Boot block hasn't got boot flag (0xAA55)"); 201 - fclose(file); 202 - 203 - /* Pad unused space with zeros */ 204 - setup_sectors = (c + 4095) / 4096; 205 - setup_sectors *= 8; 206 - if (setup_sectors < SETUP_SECT_MIN) 207 - setup_sectors = SETUP_SECT_MIN; 208 - i = setup_sectors*512; 209 - memset(buf+c, 0, i-c); 210 - 211 - /* Open and stat the kernel file */ 212 - fd = open(argv[2], O_RDONLY); 213 - if (fd < 0) 214 - die("Unable to open `%s': %m", argv[2]); 215 - if (fstat(fd, &sb)) 216 - die("Unable to stat `%s': %m", argv[2]); 217 - if (_edata != sb.st_size) 218 - die("Unexpected file size `%s': %u != %u", argv[2], _edata, 219 - sb.st_size); 220 - sz = _edata - 4; 221 - kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 222 - if (kernel == MAP_FAILED) 223 - die("Unable to mmap '%s': %m", argv[2]); 224 - 225 - crc = partial_crc32(buf, i, crc); 226 - if (fwrite(buf, 1, i, dest) != i) 227 - die("Writing setup failed"); 228 - 229 - /* Copy the kernel code */ 230 - crc = partial_crc32(kernel, sz, crc); 231 - if (fwrite(kernel, 1, sz, dest) != sz) 232 - die("Writing kernel failed"); 233 - 234 - /* Write the CRC */ 235 - put_unaligned_le32(crc, buf); 236 - if (fwrite(buf, 1, 4, dest) != 4) 237 - die("Writing CRC failed"); 238 - 239 - /* Catch any delayed write failures */ 240 - if (fclose(dest)) 241 - die("Writing image failed"); 242 - 243 - close(fd); 244 - 245 - /* Everything is OK */ 246 - return 0; 247 - }