0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "misc.h"
0016 #include "error.h"
0017 #include "pgtable.h"
0018 #include "../string.h"
0019 #include "../voffset.h"
0020 #include <asm/bootparam_utils.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #define STATIC static
0031
0032 #define MALLOC_VISIBLE
0033 #include <linux/decompress/mm.h>
0034
0035
0036
0037
0038
0039 #define memzero(s, n) memset((s), 0, (n))
0040 #ifndef memmove
0041 #define memmove memmove
0042
0043 void *memmove(void *dest, const void *src, size_t n);
0044 #endif
0045
0046
0047
0048
0049 struct boot_params *boot_params;
0050
0051 struct port_io_ops pio_ops;
0052
0053 memptr free_mem_ptr;
0054 memptr free_mem_end_ptr;
0055
0056 static char *vidmem;
0057 static int vidport;
0058
0059
0060 static int lines __section(".data");
0061 static int cols __section(".data");
0062
0063 #ifdef CONFIG_KERNEL_GZIP
0064 #include "../../../../lib/decompress_inflate.c"
0065 #endif
0066
0067 #ifdef CONFIG_KERNEL_BZIP2
0068 #include "../../../../lib/decompress_bunzip2.c"
0069 #endif
0070
0071 #ifdef CONFIG_KERNEL_LZMA
0072 #include "../../../../lib/decompress_unlzma.c"
0073 #endif
0074
0075 #ifdef CONFIG_KERNEL_XZ
0076 #include "../../../../lib/decompress_unxz.c"
0077 #endif
0078
0079 #ifdef CONFIG_KERNEL_LZO
0080 #include "../../../../lib/decompress_unlzo.c"
0081 #endif
0082
0083 #ifdef CONFIG_KERNEL_LZ4
0084 #include "../../../../lib/decompress_unlz4.c"
0085 #endif
0086
0087 #ifdef CONFIG_KERNEL_ZSTD
0088 #include "../../../../lib/decompress_unzstd.c"
0089 #endif
0090
0091
0092
0093
0094
0095 static void scroll(void)
0096 {
0097 int i;
0098
0099 memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
0100 for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
0101 vidmem[i] = ' ';
0102 }
0103
0104 #define XMTRDY 0x20
0105
0106 #define TXR 0
0107 #define LSR 5
0108 static void serial_putchar(int ch)
0109 {
0110 unsigned timeout = 0xffff;
0111
0112 while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
0113 cpu_relax();
0114
0115 outb(ch, early_serial_base + TXR);
0116 }
0117
0118 void __putstr(const char *s)
0119 {
0120 int x, y, pos;
0121 char c;
0122
0123 if (early_serial_base) {
0124 const char *str = s;
0125 while (*str) {
0126 if (*str == '\n')
0127 serial_putchar('\r');
0128 serial_putchar(*str++);
0129 }
0130 }
0131
0132 if (lines == 0 || cols == 0)
0133 return;
0134
0135 x = boot_params->screen_info.orig_x;
0136 y = boot_params->screen_info.orig_y;
0137
0138 while ((c = *s++) != '\0') {
0139 if (c == '\n') {
0140 x = 0;
0141 if (++y >= lines) {
0142 scroll();
0143 y--;
0144 }
0145 } else {
0146 vidmem[(x + cols * y) * 2] = c;
0147 if (++x >= cols) {
0148 x = 0;
0149 if (++y >= lines) {
0150 scroll();
0151 y--;
0152 }
0153 }
0154 }
0155 }
0156
0157 boot_params->screen_info.orig_x = x;
0158 boot_params->screen_info.orig_y = y;
0159
0160 pos = (x + cols * y) * 2;
0161 outb(14, vidport);
0162 outb(0xff & (pos >> 9), vidport+1);
0163 outb(15, vidport);
0164 outb(0xff & (pos >> 1), vidport+1);
0165 }
0166
0167 void __puthex(unsigned long value)
0168 {
0169 char alpha[2] = "0";
0170 int bits;
0171
0172 for (bits = sizeof(value) * 8 - 4; bits >= 0; bits -= 4) {
0173 unsigned long digit = (value >> bits) & 0xf;
0174
0175 if (digit < 0xA)
0176 alpha[0] = '0' + digit;
0177 else
0178 alpha[0] = 'a' + (digit - 0xA);
0179
0180 __putstr(alpha);
0181 }
0182 }
0183
0184 #ifdef CONFIG_X86_NEED_RELOCS
0185 static void handle_relocations(void *output, unsigned long output_len,
0186 unsigned long virt_addr)
0187 {
0188 int *reloc;
0189 unsigned long delta, map, ptr;
0190 unsigned long min_addr = (unsigned long)output;
0191 unsigned long max_addr = min_addr + (VO___bss_start - VO__text);
0192
0193
0194
0195
0196
0197 delta = min_addr - LOAD_PHYSICAL_ADDR;
0198
0199
0200
0201
0202
0203
0204
0205
0206 map = delta - __START_KERNEL_map;
0207
0208
0209
0210
0211
0212
0213 if (IS_ENABLED(CONFIG_X86_64))
0214 delta = virt_addr - LOAD_PHYSICAL_ADDR;
0215
0216 if (!delta) {
0217 debug_putstr("No relocation needed... ");
0218 return;
0219 }
0220 debug_putstr("Performing relocations... ");
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 for (reloc = output + output_len - sizeof(*reloc); *reloc; reloc--) {
0242 long extended = *reloc;
0243 extended += map;
0244
0245 ptr = (unsigned long)extended;
0246 if (ptr < min_addr || ptr > max_addr)
0247 error("32-bit relocation outside of kernel!\n");
0248
0249 *(uint32_t *)ptr += delta;
0250 }
0251 #ifdef CONFIG_X86_64
0252 while (*--reloc) {
0253 long extended = *reloc;
0254 extended += map;
0255
0256 ptr = (unsigned long)extended;
0257 if (ptr < min_addr || ptr > max_addr)
0258 error("inverse 32-bit relocation outside of kernel!\n");
0259
0260 *(int32_t *)ptr -= delta;
0261 }
0262 for (reloc--; *reloc; reloc--) {
0263 long extended = *reloc;
0264 extended += map;
0265
0266 ptr = (unsigned long)extended;
0267 if (ptr < min_addr || ptr > max_addr)
0268 error("64-bit relocation outside of kernel!\n");
0269
0270 *(uint64_t *)ptr += delta;
0271 }
0272 #endif
0273 }
0274 #else
0275 static inline void handle_relocations(void *output, unsigned long output_len,
0276 unsigned long virt_addr)
0277 { }
0278 #endif
0279
0280 static void parse_elf(void *output)
0281 {
0282 #ifdef CONFIG_X86_64
0283 Elf64_Ehdr ehdr;
0284 Elf64_Phdr *phdrs, *phdr;
0285 #else
0286 Elf32_Ehdr ehdr;
0287 Elf32_Phdr *phdrs, *phdr;
0288 #endif
0289 void *dest;
0290 int i;
0291
0292 memcpy(&ehdr, output, sizeof(ehdr));
0293 if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
0294 ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
0295 ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
0296 ehdr.e_ident[EI_MAG3] != ELFMAG3) {
0297 error("Kernel is not a valid ELF file");
0298 return;
0299 }
0300
0301 debug_putstr("Parsing ELF... ");
0302
0303 phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
0304 if (!phdrs)
0305 error("Failed to allocate space for phdrs");
0306
0307 memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);
0308
0309 for (i = 0; i < ehdr.e_phnum; i++) {
0310 phdr = &phdrs[i];
0311
0312 switch (phdr->p_type) {
0313 case PT_LOAD:
0314 #ifdef CONFIG_X86_64
0315 if ((phdr->p_align % 0x200000) != 0)
0316 error("Alignment of LOAD segment isn't multiple of 2MB");
0317 #endif
0318 #ifdef CONFIG_RELOCATABLE
0319 dest = output;
0320 dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
0321 #else
0322 dest = (void *)(phdr->p_paddr);
0323 #endif
0324 memmove(dest, output + phdr->p_offset, phdr->p_filesz);
0325 break;
0326 default: break;
0327 }
0328 }
0329
0330 free(phdrs);
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
0351 unsigned char *input_data,
0352 unsigned long input_len,
0353 unsigned char *output,
0354 unsigned long output_len)
0355 {
0356 const unsigned long kernel_total_size = VO__end - VO__text;
0357 unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
0358 unsigned long needed_size;
0359
0360
0361 boot_params = rmode;
0362
0363
0364 boot_params->hdr.loadflags &= ~KASLR_FLAG;
0365
0366 sanitize_boot_params(boot_params);
0367
0368 if (boot_params->screen_info.orig_video_mode == 7) {
0369 vidmem = (char *) 0xb0000;
0370 vidport = 0x3b4;
0371 } else {
0372 vidmem = (char *) 0xb8000;
0373 vidport = 0x3d4;
0374 }
0375
0376 lines = boot_params->screen_info.orig_video_lines;
0377 cols = boot_params->screen_info.orig_video_cols;
0378
0379 init_default_io_ops();
0380
0381
0382
0383
0384
0385
0386
0387 early_tdx_detect();
0388
0389 console_init();
0390
0391
0392
0393
0394
0395
0396 boot_params->acpi_rsdp_addr = get_rsdp_addr();
0397
0398 debug_putstr("early console in extract_kernel\n");
0399
0400 free_mem_ptr = heap;
0401 free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414 needed_size = max(output_len, kernel_total_size);
0415 #ifdef CONFIG_X86_64
0416 needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN);
0417 #endif
0418
0419
0420 debug_putaddr(input_data);
0421 debug_putaddr(input_len);
0422 debug_putaddr(output);
0423 debug_putaddr(output_len);
0424 debug_putaddr(kernel_total_size);
0425 debug_putaddr(needed_size);
0426
0427 #ifdef CONFIG_X86_64
0428
0429 debug_putaddr(trampoline_32bit);
0430 #endif
0431
0432 choose_random_location((unsigned long)input_data, input_len,
0433 (unsigned long *)&output,
0434 needed_size,
0435 &virt_addr);
0436
0437
0438 if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
0439 error("Destination physical address inappropriately aligned");
0440 if (virt_addr & (MIN_KERNEL_ALIGN - 1))
0441 error("Destination virtual address inappropriately aligned");
0442 #ifdef CONFIG_X86_64
0443 if (heap > 0x3fffffffffffUL)
0444 error("Destination address too large");
0445 if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE)
0446 error("Destination virtual address is beyond the kernel mapping area");
0447 #else
0448 if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
0449 error("Destination address too large");
0450 #endif
0451 #ifndef CONFIG_RELOCATABLE
0452 if (virt_addr != LOAD_PHYSICAL_ADDR)
0453 error("Destination virtual address changed when not relocatable");
0454 #endif
0455
0456 debug_putstr("\nDecompressing Linux... ");
0457 __decompress(input_data, input_len, NULL, NULL, output, output_len,
0458 NULL, error);
0459 parse_elf(output);
0460 handle_relocations(output, output_len, virt_addr);
0461 debug_putstr("done.\nBooting the kernel.\n");
0462
0463
0464 cleanup_exception_handling();
0465
0466 return output;
0467 }
0468
0469 void fortify_panic(const char *name)
0470 {
0471 error("detected buffer overflow");
0472 }