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

Merge tag 'efi-next-for-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel:
"The usual trickle of EFI contributions:

- Parse SMBIOS tables in memory directly on Macbooks that do not
implement the EFI SMBIOS protocol

- Obtain EDID information from the primary display while running in
the EFI stub, and expose it via bootparams on x86 (generic method
is in the works, and will likely land during the next cycle)

- Bring CPER handling for ARM systems up to data with the latest EFI
spec changes

- Various cosmetic changes"

* tag 'efi-next-for-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
docs: efi: add CPER functions to driver-api
efi/cper: align ARM CPER type with UEFI 2.9A/2.10 specs
efi/cper: Add a new helper function to print bitmasks
efi/cper: Adjust infopfx size to accept an extra space
RAS: Report all ARM processor CPER information to userspace
efi/libstub: x86: Store EDID in boot_params
efi/libstub: gop: Add support for reading EDID
efi/libstub: gop: Initialize screen_info in helper function
efi/libstub: gop: Find GOP handle instead of GOP data
efi: Fix trailing whitespace in header file
efi/memattr: Convert efi_memattr_init() return type to void
efi: stmm: fix kernel-doc "bad line" warnings
efi/riscv: Remove the useless failure return message print
efistub/x86: Add fallback for SMBIOS record lookup

+436 -132
+8 -3
Documentation/driver-api/firmware/efi/index.rst
··· 1 1 .. SPDX-License-Identifier: GPL-2.0 2 2 3 - ============ 4 - UEFI Support 5 - ============ 3 + ==================================================== 4 + Unified Extensible Firmware Interface (UEFI) Support 5 + ==================================================== 6 6 7 7 UEFI stub library functions 8 8 =========================== 9 9 10 10 .. kernel-doc:: drivers/firmware/efi/libstub/mem.c 11 11 :internal: 12 + 13 + UEFI Common Platform Error Record (CPER) functions 14 + ================================================== 15 + 16 + .. kernel-doc:: drivers/firmware/efi/cper.c
+14 -13
drivers/acpi/apei/ghes.c
··· 22 22 #include <linux/moduleparam.h> 23 23 #include <linux/init.h> 24 24 #include <linux/acpi.h> 25 + #include <linux/bitfield.h> 25 26 #include <linux/io.h> 26 27 #include <linux/interrupt.h> 27 28 #include <linux/timer.h> ··· 553 552 } 554 553 555 554 static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, 556 - int sev, bool sync) 555 + int sev, bool sync) 557 556 { 558 557 struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); 559 558 int flags = sync ? MF_ACTION_REQUIRED : 0; 559 + char error_type[120]; 560 560 bool queued = false; 561 561 int sec_sev, i; 562 562 char *p; 563 563 564 - log_arm_hw_error(err); 565 - 566 564 sec_sev = ghes_severity(gdata->error_severity); 565 + log_arm_hw_error(err, sec_sev); 567 566 if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE) 568 567 return false; 569 568 570 569 p = (char *)(err + 1); 571 570 for (i = 0; i < err->err_info_num; i++) { 572 571 struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p; 573 - bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR); 572 + bool is_cache = err_info->type & CPER_ARM_CACHE_ERROR; 574 573 bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR); 575 - const char *error_type = "unknown error"; 576 574 577 575 /* 578 576 * The field (err_info->error_info & BIT(26)) is fixed to set to ··· 585 585 continue; 586 586 } 587 587 588 - if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs)) 589 - error_type = cper_proc_error_type_strs[err_info->type]; 588 + cper_bits_to_str(error_type, sizeof(error_type), 589 + FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type), 590 + cper_proc_error_type_strs, 591 + ARRAY_SIZE(cper_proc_error_type_strs)); 590 592 591 593 pr_warn_ratelimited(FW_WARN GHES_PFX 592 - "Unhandled processor error type: %s\n", 593 - error_type); 594 + "Unhandled processor error type 0x%02x: %s%s\n", 595 + err_info->type, error_type, 596 + (err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : ""); 594 597 p += err_info->length; 595 598 } 596 599 ··· 898 895 899 896 arch_apei_report_mem_error(sev, mem_err); 900 897 queued = ghes_handle_memory_failure(gdata, sev, sync); 901 - } 902 - else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { 898 + } else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { 903 899 ghes_handle_aer(gdata); 904 - } 905 - else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { 900 + } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { 906 901 queued = ghes_handle_arm_hw_error(gdata, sev, sync); 907 902 } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) { 908 903 struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);
+25 -27
drivers/firmware/efi/cper-arm.c
··· 93 93 bool proc_context_corrupt, corrected, precise_pc, restartable_pc; 94 94 bool time_out, access_mode; 95 95 96 - /* If the type is unknown, bail. */ 97 - if (type > CPER_ARM_MAX_TYPE) 98 - return; 99 - 100 96 /* 101 97 * Vendor type errors have error information values that are vendor 102 98 * specific. 103 99 */ 104 - if (type == CPER_ARM_VENDOR_ERROR) 100 + if (type & CPER_ARM_VENDOR_ERROR) 105 101 return; 106 102 107 103 if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) { ··· 112 116 if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) { 113 117 op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT) 114 118 & CPER_ARM_ERR_OPERATION_MASK); 115 - switch (type) { 116 - case CPER_ARM_CACHE_ERROR: 119 + if (type & CPER_ARM_CACHE_ERROR) { 117 120 if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) { 118 - printk("%soperation type: %s\n", pfx, 121 + printk("%scache error, operation type: %s\n", pfx, 119 122 arm_cache_err_op_strs[op_type]); 120 123 } 121 - break; 122 - case CPER_ARM_TLB_ERROR: 124 + } 125 + if (type & CPER_ARM_TLB_ERROR) { 123 126 if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) { 124 - printk("%soperation type: %s\n", pfx, 127 + printk("%sTLB error, operation type: %s\n", pfx, 125 128 arm_tlb_err_op_strs[op_type]); 126 129 } 127 - break; 128 - case CPER_ARM_BUS_ERROR: 130 + } 131 + if (type & CPER_ARM_BUS_ERROR) { 129 132 if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) { 130 - printk("%soperation type: %s\n", pfx, 133 + printk("%sbus error, operation type: %s\n", pfx, 131 134 arm_bus_err_op_strs[op_type]); 132 135 } 133 - break; 134 136 } 135 137 } 136 138 137 139 if (error_info & CPER_ARM_ERR_VALID_LEVEL) { 138 140 level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT) 139 141 & CPER_ARM_ERR_LEVEL_MASK); 140 - switch (type) { 141 - case CPER_ARM_CACHE_ERROR: 142 + if (type & CPER_ARM_CACHE_ERROR) 142 143 printk("%scache level: %d\n", pfx, level); 143 - break; 144 - case CPER_ARM_TLB_ERROR: 144 + 145 + if (type & CPER_ARM_TLB_ERROR) 145 146 printk("%sTLB level: %d\n", pfx, level); 146 - break; 147 - case CPER_ARM_BUS_ERROR: 147 + 148 + if (type & CPER_ARM_BUS_ERROR) 148 149 printk("%saffinity level at which the bus error occurred: %d\n", 149 150 pfx, level); 150 - break; 151 - } 152 151 } 153 152 154 153 if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) { ··· 231 240 int i, len, max_ctx_type; 232 241 struct cper_arm_err_info *err_info; 233 242 struct cper_arm_ctx_info *ctx_info; 234 - char newpfx[64], infopfx[64]; 243 + char newpfx[64], infopfx[ARRAY_SIZE(newpfx) + 1]; 244 + char error_type[120]; 235 245 236 246 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr); 237 247 ··· 281 289 newpfx); 282 290 } 283 291 284 - printk("%serror_type: %d, %s\n", newpfx, err_info->type, 285 - err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ? 286 - cper_proc_error_type_strs[err_info->type] : "unknown"); 292 + cper_bits_to_str(error_type, sizeof(error_type), 293 + FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type), 294 + cper_proc_error_type_strs, 295 + ARRAY_SIZE(cper_proc_error_type_strs)); 296 + 297 + printk("%serror_type: 0x%02x: %s%s\n", newpfx, err_info->type, 298 + error_type, 299 + (err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : ""); 300 + 287 301 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) { 288 302 printk("%serror_info: 0x%016llx\n", newpfx, 289 303 err_info->error_info);
+61 -1
drivers/firmware/efi/cper.c
··· 12 12 * Specification version 2.4. 13 13 */ 14 14 15 + #include <linux/bitmap.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/module.h> 17 18 #include <linux/time.h> ··· 70 69 } 71 70 EXPORT_SYMBOL_GPL(cper_severity_str); 72 71 73 - /* 72 + /** 74 73 * cper_print_bits - print strings for set bits 75 74 * @pfx: prefix for each line, including log level and prefix string 76 75 * @bits: bit mask ··· 106 105 if (len) 107 106 printk("%s\n", buf); 108 107 } 108 + 109 + /** 110 + * cper_bits_to_str - return a string for set bits 111 + * @buf: buffer to store the output string 112 + * @buf_size: size of the output string buffer 113 + * @bits: bit mask 114 + * @strs: string array, indexed by bit position 115 + * @strs_size: size of the string array: @strs 116 + * 117 + * Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits, 118 + * add the corresponding string describing the bit in @strs to @buf. 119 + * 120 + * A typical example is:: 121 + * 122 + * const char * const bits[] = { 123 + * "bit 3 name", 124 + * "bit 4 name", 125 + * "bit 5 name", 126 + * }; 127 + * char str[120]; 128 + * unsigned int bitmask = BIT(3) | BIT(5); 129 + * #define MASK GENMASK(5,3) 130 + * 131 + * cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask), 132 + * bits, ARRAY_SIZE(bits)); 133 + * 134 + * The above code fills the string ``str`` with ``bit 3 name|bit 5 name``. 135 + * 136 + * Return: number of bytes stored or an error code if lower than zero. 137 + */ 138 + int cper_bits_to_str(char *buf, int buf_size, unsigned long bits, 139 + const char * const strs[], unsigned int strs_size) 140 + { 141 + int len = buf_size; 142 + char *str = buf; 143 + int i, size; 144 + 145 + *buf = '\0'; 146 + 147 + for_each_set_bit(i, &bits, strs_size) { 148 + if (!(bits & BIT_ULL(i))) 149 + continue; 150 + 151 + if (*buf && len > 0) { 152 + *str = '|'; 153 + len--; 154 + str++; 155 + } 156 + 157 + size = strscpy(str, strs[i], len); 158 + if (size < 0) 159 + return size; 160 + 161 + len -= size; 162 + str += size; 163 + } 164 + return len - buf_size; 165 + } 166 + EXPORT_SYMBOL_GPL(cper_bits_to_str); 109 167 110 168 static const char * const proc_type_strs[] = { 111 169 "IA32/X64",
+1 -1
drivers/firmware/efi/libstub/efi-stub.c
··· 56 56 { 57 57 struct screen_info *si, tmp = {}; 58 58 59 - if (efi_setup_gop(&tmp) != EFI_SUCCESS) 59 + if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS) 60 60 return NULL; 61 61 62 62 si = alloc_screen_info();
+30 -1
drivers/firmware/efi/libstub/efistub.h
··· 34 34 #define EFI_ALLOC_LIMIT ULONG_MAX 35 35 #endif 36 36 37 + struct edid_info; 38 + struct screen_info; 39 + 37 40 extern bool efi_no5lvl; 38 41 extern bool efi_nochunk; 39 42 extern bool efi_nokaslr; ··· 581 578 } mixed_mode; 582 579 }; 583 580 581 + typedef union efi_edid_discovered_protocol efi_edid_discovered_protocol_t; 582 + 583 + union efi_edid_discovered_protocol { 584 + struct { 585 + u32 size_of_edid; 586 + u8 *edid; 587 + }; 588 + struct { 589 + u32 size_of_edid; 590 + u32 edid; 591 + } mixed_mode; 592 + }; 593 + 594 + typedef union efi_edid_active_protocol efi_edid_active_protocol_t; 595 + 596 + union efi_edid_active_protocol { 597 + struct { 598 + u32 size_of_edid; 599 + u8 *edid; 600 + }; 601 + struct { 602 + u32 size_of_edid; 603 + u32 edid; 604 + } mixed_mode; 605 + }; 606 + 584 607 typedef union { 585 608 struct { 586 609 u32 revision; ··· 1114 1085 1115 1086 void efi_parse_option_graphics(char *option); 1116 1087 1117 - efi_status_t efi_setup_gop(struct screen_info *si); 1088 + efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid); 1118 1089 1119 1090 efi_status_t handle_cmdline_files(efi_loaded_image_t *image, 1120 1091 const efi_char16_t *optstr,
+82 -51
drivers/firmware/efi/libstub/gop.c
··· 12 12 #include <linux/string.h> 13 13 #include <asm/efi.h> 14 14 #include <asm/setup.h> 15 + #include <video/edid.h> 15 16 16 17 #include "efistub.h" 17 18 ··· 368 367 *size = __fls(mask) - *pos + 1; 369 368 } 370 369 371 - static void 372 - setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line, 373 - efi_pixel_bitmask_t pixel_info, int pixel_format) 370 + static void setup_screen_info(struct screen_info *si, const efi_graphics_output_protocol_t *gop) 374 371 { 375 - if (pixel_format == PIXEL_BIT_MASK) { 376 - find_bits(pixel_info.red_mask, 377 - &si->red_pos, &si->red_size); 378 - find_bits(pixel_info.green_mask, 379 - &si->green_pos, &si->green_size); 380 - find_bits(pixel_info.blue_mask, 381 - &si->blue_pos, &si->blue_size); 382 - find_bits(pixel_info.reserved_mask, 383 - &si->rsvd_pos, &si->rsvd_size); 384 - si->lfb_depth = si->red_size + si->green_size + 385 - si->blue_size + si->rsvd_size; 386 - si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8; 372 + const efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode); 373 + const efi_graphics_output_mode_info_t *info = efi_table_attr(mode, info); 374 + 375 + si->orig_video_isVGA = VIDEO_TYPE_EFI; 376 + 377 + si->lfb_width = info->horizontal_resolution; 378 + si->lfb_height = info->vertical_resolution; 379 + 380 + efi_set_u64_split(efi_table_attr(mode, frame_buffer_base), 381 + &si->lfb_base, &si->ext_lfb_base); 382 + if (si->ext_lfb_base) 383 + si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; 384 + si->pages = 1; 385 + 386 + if (info->pixel_format == PIXEL_BIT_MASK) { 387 + find_bits(info->pixel_information.red_mask, &si->red_pos, &si->red_size); 388 + find_bits(info->pixel_information.green_mask, &si->green_pos, &si->green_size); 389 + find_bits(info->pixel_information.blue_mask, &si->blue_pos, &si->blue_size); 390 + find_bits(info->pixel_information.reserved_mask, &si->rsvd_pos, &si->rsvd_size); 391 + si->lfb_depth = si->red_size + si->green_size + si->blue_size + si->rsvd_size; 392 + si->lfb_linelength = (info->pixels_per_scan_line * si->lfb_depth) / 8; 387 393 } else { 388 - if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 394 + if (info->pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 389 395 si->red_pos = 0; 390 396 si->blue_pos = 16; 391 397 } else /* PIXEL_BGR_RESERVED_8BIT_PER_COLOR */ { ··· 402 394 403 395 si->green_pos = 8; 404 396 si->rsvd_pos = 24; 405 - si->red_size = si->green_size = 406 - si->blue_size = si->rsvd_size = 8; 407 - 397 + si->red_size = 8; 398 + si->green_size = 8; 399 + si->blue_size = 8; 400 + si->rsvd_size = 8; 408 401 si->lfb_depth = 32; 409 - si->lfb_linelength = pixels_per_scan_line * 4; 402 + si->lfb_linelength = info->pixels_per_scan_line * 4; 410 403 } 404 + 405 + si->lfb_size = si->lfb_linelength * si->lfb_height; 406 + si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 411 407 } 412 408 413 - static efi_graphics_output_protocol_t *find_gop(unsigned long num, 414 - const efi_handle_t handles[]) 409 + static void setup_edid_info(struct edid_info *edid, u32 gop_size_of_edid, u8 *gop_edid) 410 + { 411 + if (!gop_edid || gop_size_of_edid < 128) 412 + memset(edid->dummy, 0, sizeof(edid->dummy)); 413 + else 414 + memcpy(edid->dummy, gop_edid, min(gop_size_of_edid, sizeof(edid->dummy))); 415 + } 416 + 417 + static efi_handle_t find_handle_with_primary_gop(unsigned long num, const efi_handle_t handles[], 418 + efi_graphics_output_protocol_t **found_gop) 415 419 { 416 420 efi_graphics_output_protocol_t *first_gop; 417 - efi_handle_t h; 421 + efi_handle_t h, first_gop_handle; 418 422 423 + first_gop_handle = NULL; 419 424 first_gop = NULL; 420 425 421 426 for_each_efi_handle(h, handles, num) { ··· 463 442 */ 464 443 status = efi_bs_call(handle_protocol, h, 465 444 &EFI_CONSOLE_OUT_DEVICE_GUID, &dummy); 466 - if (status == EFI_SUCCESS) 467 - return gop; 468 - 469 - if (!first_gop) 445 + if (status == EFI_SUCCESS) { 446 + if (found_gop) 447 + *found_gop = gop; 448 + return h; 449 + } else if (!first_gop_handle) { 450 + first_gop_handle = h; 470 451 first_gop = gop; 452 + } 471 453 } 472 454 473 - return first_gop; 455 + if (found_gop) 456 + *found_gop = first_gop; 457 + return first_gop_handle; 474 458 } 475 459 476 - efi_status_t efi_setup_gop(struct screen_info *si) 460 + efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid) 477 461 { 478 462 efi_handle_t *handles __free(efi_pool) = NULL; 479 - efi_graphics_output_protocol_mode_t *mode; 480 - efi_graphics_output_mode_info_t *info; 463 + efi_handle_t handle; 481 464 efi_graphics_output_protocol_t *gop; 482 465 efi_status_t status; 483 466 unsigned long num; ··· 492 467 if (status != EFI_SUCCESS) 493 468 return status; 494 469 495 - gop = find_gop(num, handles); 496 - if (!gop) 470 + handle = find_handle_with_primary_gop(num, handles, &gop); 471 + if (!handle) 497 472 return EFI_NOT_FOUND; 498 473 499 474 /* Change mode if requested */ 500 475 set_mode(gop); 501 476 502 477 /* EFI framebuffer */ 503 - mode = efi_table_attr(gop, mode); 504 - info = efi_table_attr(mode, info); 478 + if (si) 479 + setup_screen_info(si, gop); 505 480 506 - si->orig_video_isVGA = VIDEO_TYPE_EFI; 481 + /* Display EDID for primary GOP */ 482 + if (edid) { 483 + efi_edid_discovered_protocol_t *discovered_edid; 484 + efi_edid_active_protocol_t *active_edid; 485 + u32 gop_size_of_edid = 0; 486 + u8 *gop_edid = NULL; 507 487 508 - si->lfb_width = info->horizontal_resolution; 509 - si->lfb_height = info->vertical_resolution; 488 + status = efi_bs_call(handle_protocol, handle, &EFI_EDID_ACTIVE_PROTOCOL_GUID, 489 + (void **)&active_edid); 490 + if (status == EFI_SUCCESS) { 491 + gop_size_of_edid = active_edid->size_of_edid; 492 + gop_edid = active_edid->edid; 493 + } else { 494 + status = efi_bs_call(handle_protocol, handle, 495 + &EFI_EDID_DISCOVERED_PROTOCOL_GUID, 496 + (void **)&discovered_edid); 497 + if (status == EFI_SUCCESS) { 498 + gop_size_of_edid = discovered_edid->size_of_edid; 499 + gop_edid = discovered_edid->edid; 500 + } 501 + } 510 502 511 - efi_set_u64_split(efi_table_attr(mode, frame_buffer_base), 512 - &si->lfb_base, &si->ext_lfb_base); 513 - if (si->ext_lfb_base) 514 - si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; 515 - 516 - si->pages = 1; 517 - 518 - setup_pixel_info(si, info->pixels_per_scan_line, 519 - info->pixel_information, info->pixel_format); 520 - 521 - si->lfb_size = si->lfb_linelength * si->lfb_height; 522 - 523 - si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 503 + setup_edid_info(edid, gop_size_of_edid, gop_edid); 504 + } 524 505 525 506 return EFI_SUCCESS; 526 507 }
+102 -2
drivers/firmware/efi/libstub/x86-stub.c
··· 203 203 } 204 204 } 205 205 206 + struct smbios_entry_point { 207 + u8 anchor[4]; 208 + u8 ep_checksum; 209 + u8 ep_length; 210 + u8 major_version; 211 + u8 minor_version; 212 + u16 max_size_entry; 213 + u8 ep_rev; 214 + u8 reserved[5]; 215 + 216 + struct __packed { 217 + u8 anchor[5]; 218 + u8 checksum; 219 + u16 st_length; 220 + u32 st_address; 221 + u16 number_of_entries; 222 + u8 bcd_rev; 223 + } intm; 224 + }; 225 + 226 + static bool verify_ep_checksum(const void *ptr, int length) 227 + { 228 + u8 sum = 0; 229 + 230 + for (int i = 0; i < length; i++) 231 + sum += ((u8 *)ptr)[i]; 232 + 233 + return sum == 0; 234 + } 235 + 236 + static bool verify_ep_integrity(const struct smbios_entry_point *ep) 237 + { 238 + if (memcmp(ep->anchor, "_SM_", sizeof(ep->anchor)) != 0) 239 + return false; 240 + 241 + if (memcmp(ep->intm.anchor, "_DMI_", sizeof(ep->intm.anchor)) != 0) 242 + return false; 243 + 244 + if (!verify_ep_checksum(ep, ep->ep_length) || 245 + !verify_ep_checksum(&ep->intm, sizeof(ep->intm))) 246 + return false; 247 + 248 + return true; 249 + } 250 + 251 + static const struct efi_smbios_record *search_record(void *table, u32 length, 252 + u8 type) 253 + { 254 + const u8 *p, *end; 255 + 256 + p = (u8 *)table; 257 + end = p + length; 258 + 259 + while (p + sizeof(struct efi_smbios_record) < end) { 260 + const struct efi_smbios_record *hdr = 261 + (struct efi_smbios_record *)p; 262 + const u8 *next; 263 + 264 + if (hdr->type == type) 265 + return hdr; 266 + 267 + /* Type 127 = End-of-Table */ 268 + if (hdr->type == 0x7F) 269 + return NULL; 270 + 271 + /* Jumping to the unformed section */ 272 + next = p + hdr->length; 273 + 274 + /* Unformed section ends with 0000h */ 275 + while ((next[0] != 0 || next[1] != 0) && next + 1 < end) 276 + next++; 277 + 278 + next += 2; 279 + p = next; 280 + } 281 + 282 + return NULL; 283 + } 284 + 285 + static const struct efi_smbios_record *get_table_record(u8 type) 286 + { 287 + const struct smbios_entry_point *ep; 288 + 289 + /* 290 + * Locate the legacy 32-bit SMBIOS entrypoint in memory, and parse it 291 + * directly. Needed by some Macs that do not implement the EFI protocol. 292 + */ 293 + ep = get_efi_config_table(SMBIOS_TABLE_GUID); 294 + if (!ep) 295 + return NULL; 296 + 297 + if (!verify_ep_integrity(ep)) 298 + return NULL; 299 + 300 + return search_record((void *)(unsigned long)ep->intm.st_address, 301 + ep->intm.st_length, type); 302 + } 303 + 206 304 static bool apple_match_product_name(void) 207 305 { 208 306 static const char type1_product_matches[][15] = { ··· 316 218 const struct efi_smbios_type1_record *record; 317 219 const u8 *product; 318 220 319 - record = (struct efi_smbios_type1_record *)efi_get_smbios_record(1); 221 + record = (struct efi_smbios_type1_record *) 222 + (efi_get_smbios_record(1) ?: get_table_record(1)); 320 223 if (!record) 321 224 return false; 322 225 ··· 487 388 static void setup_graphics(struct boot_params *boot_params) 488 389 { 489 390 struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si)); 391 + struct edid_info *edid = memset(&boot_params->edid_info, 0, sizeof(*edid)); 490 392 491 - efi_setup_gop(si); 393 + efi_setup_graphics(si, edid); 492 394 } 493 395 494 396 static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
+3 -4
drivers/firmware/efi/memattr.c
··· 19 19 * Reserve the memory associated with the Memory Attributes configuration 20 20 * table, if it exists. 21 21 */ 22 - int __init efi_memattr_init(void) 22 + void __init efi_memattr_init(void) 23 23 { 24 24 efi_memory_attributes_table_t *tbl; 25 25 unsigned long size; 26 26 27 27 if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR) 28 - return 0; 28 + return; 29 29 30 30 tbl = early_memremap(efi_mem_attr_table, sizeof(*tbl)); 31 31 if (!tbl) { 32 32 pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n", 33 33 efi_mem_attr_table); 34 - return -ENOMEM; 34 + return; 35 35 } 36 36 37 37 if (tbl->version > 2) { ··· 61 61 62 62 unmap: 63 63 early_memunmap(tbl, sizeof(*tbl)); 64 - return 0; 65 64 } 66 65 67 66 /*
+1 -9
drivers/firmware/efi/riscv-runtime.c
··· 36 36 init_new_context(NULL, &efi_mm); 37 37 38 38 for_each_efi_memory_desc(md) { 39 - phys_addr_t phys = md->phys_addr; 40 - int ret; 41 - 42 39 if (!(md->attribute & EFI_MEMORY_RUNTIME)) 43 40 continue; 44 41 if (md->virt_addr == U64_MAX) 45 42 return false; 46 43 47 - ret = efi_create_mapping(&efi_mm, md); 48 - if (ret) { 49 - pr_warn(" EFI remap %pa: failed to create mapping (%d)\n", 50 - &phys, ret); 51 - return false; 52 - } 44 + efi_create_mapping(&efi_mm, md); 53 45 } 54 46 55 47 if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions))
+3 -3
drivers/firmware/efi/stmm/mm_communication.h
··· 32 32 33 33 /** 34 34 * struct efi_mm_communicate_header - Header used for SMM variable communication 35 - 35 + * 36 36 * @header_guid: header use for disambiguation of content 37 37 * @message_len: length of the message. Does not include the size of the 38 38 * header ··· 111 111 112 112 /** 113 113 * struct smm_variable_communicate_header - Used for SMM variable communication 114 - 114 + * 115 115 * @function: function to call in Smm. 116 116 * @ret_status: return status 117 117 * @data: payload ··· 128 128 /** 129 129 * struct smm_variable_access - Used to communicate with StMM by 130 130 * SetVariable and GetVariable. 131 - 131 + * 132 132 * @guid: vendor GUID 133 133 * @data_size: size of EFI variable data 134 134 * @name_size: size of EFI name
+38 -2
drivers/ras/ras.c
··· 53 53 } 54 54 EXPORT_SYMBOL_GPL(log_non_standard_event); 55 55 56 - void log_arm_hw_error(struct cper_sec_proc_arm *err) 56 + void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev) 57 57 { 58 - trace_arm_event(err); 58 + struct cper_arm_err_info *err_info; 59 + struct cper_arm_ctx_info *ctx_info; 60 + u8 *ven_err_data; 61 + u32 ctx_len = 0; 62 + int n, sz, cpu; 63 + s32 vsei_len; 64 + u32 pei_len; 65 + u8 *pei_err, *ctx_err; 66 + 67 + pei_len = sizeof(struct cper_arm_err_info) * err->err_info_num; 68 + pei_err = (u8 *)(err + 1); 69 + 70 + err_info = (struct cper_arm_err_info *)(err + 1); 71 + ctx_info = (struct cper_arm_ctx_info *)(err_info + err->err_info_num); 72 + ctx_err = (u8 *)ctx_info; 73 + 74 + for (n = 0; n < err->context_info_num; n++) { 75 + sz = sizeof(struct cper_arm_ctx_info) + ctx_info->size; 76 + ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + sz); 77 + ctx_len += sz; 78 + } 79 + 80 + vsei_len = err->section_length - (sizeof(struct cper_sec_proc_arm) + pei_len + ctx_len); 81 + if (vsei_len < 0) { 82 + pr_warn(FW_BUG "section length: %d\n", err->section_length); 83 + pr_warn(FW_BUG "section length is too small\n"); 84 + pr_warn(FW_BUG "firmware-generated error record is incorrect\n"); 85 + vsei_len = 0; 86 + } 87 + ven_err_data = (u8 *)ctx_info; 88 + 89 + cpu = GET_LOGICAL_INDEX(err->mpidr); 90 + if (cpu < 0) 91 + cpu = -1; 92 + 93 + trace_arm_event(err, pei_err, pei_len, ctx_err, ctx_len, 94 + ven_err_data, (u32)vsei_len, sev, cpu); 59 95 } 60 96 61 97 static int __init ras_init(void)
+7 -5
include/linux/cper.h
··· 297 297 #define CPER_ARM_INFO_FLAGS_PROPAGATED BIT(2) 298 298 #define CPER_ARM_INFO_FLAGS_OVERFLOW BIT(3) 299 299 300 - #define CPER_ARM_CACHE_ERROR 0 301 - #define CPER_ARM_TLB_ERROR 1 302 - #define CPER_ARM_BUS_ERROR 2 303 - #define CPER_ARM_VENDOR_ERROR 3 304 - #define CPER_ARM_MAX_TYPE CPER_ARM_VENDOR_ERROR 300 + #define CPER_ARM_ERR_TYPE_MASK GENMASK(4,1) 301 + #define CPER_ARM_CACHE_ERROR BIT(1) 302 + #define CPER_ARM_TLB_ERROR BIT(2) 303 + #define CPER_ARM_BUS_ERROR BIT(3) 304 + #define CPER_ARM_VENDOR_ERROR BIT(4) 305 305 306 306 #define CPER_ARM_ERR_VALID_TRANSACTION_TYPE BIT(0) 307 307 #define CPER_ARM_ERR_VALID_OPERATION_TYPE BIT(1) ··· 587 587 const char *cper_mem_err_type_str(unsigned int); 588 588 const char *cper_mem_err_status_str(u64 status); 589 589 void cper_print_bits(const char *prefix, unsigned int bits, 590 + const char * const strs[], unsigned int strs_size); 591 + int cper_bits_to_str(char *buf, int buf_size, unsigned long bits, 590 592 const char * const strs[], unsigned int strs_size); 591 593 void cper_mem_err_pack(const struct cper_sec_mem_err *, 592 594 struct cper_mem_err_compact *);
+4 -2
include/linux/efi.h
··· 290 290 unsigned long *data_size, void *data); 291 291 typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, 292 292 efi_guid_t *vendor); 293 - typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, 293 + typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, 294 294 u32 attr, unsigned long data_size, 295 295 void *data); 296 296 typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); ··· 373 373 #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c) 374 374 #define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID EFI_GUID(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e) 375 375 #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) 376 + #define EFI_EDID_DISCOVERED_PROTOCOL_GUID EFI_GUID(0x1c0c34f6, 0xd380, 0x41fa, 0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa) 377 + #define EFI_EDID_ACTIVE_PROTOCOL_GUID EFI_GUID(0xbd8c1056, 0x9f36, 0x44ec, 0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86) 376 378 #define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a) 377 379 #define EFI_FILE_INFO_ID EFI_GUID(0x09576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) 378 380 #define EFI_SYSTEM_RESOURCE_TABLE_GUID EFI_GUID(0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80) ··· 774 772 */ 775 773 typedef int (*efi_memattr_perm_setter)(struct mm_struct *, efi_memory_desc_t *, bool); 776 774 777 - extern int efi_memattr_init(void); 775 + extern void efi_memattr_init(void); 778 776 extern int efi_memattr_apply_permissions(struct mm_struct *mm, 779 777 efi_memattr_perm_setter fn); 780 778
+13 -3
include/linux/ras.h
··· 24 24 void log_non_standard_event(const guid_t *sec_type, 25 25 const guid_t *fru_id, const char *fru_text, 26 26 const u8 sev, const u8 *err, const u32 len); 27 - void log_arm_hw_error(struct cper_sec_proc_arm *err); 28 - 27 + void log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev); 29 28 #else 30 29 static inline void 31 30 log_non_standard_event(const guid_t *sec_type, ··· 32 33 const u8 sev, const u8 *err, const u32 len) 33 34 { return; } 34 35 static inline void 35 - log_arm_hw_error(struct cper_sec_proc_arm *err) { return; } 36 + log_arm_hw_error(struct cper_sec_proc_arm *err, const u8 sev) { return; } 36 37 #endif 37 38 38 39 struct atl_err { ··· 51 52 static inline unsigned long 52 53 amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; } 53 54 #endif /* CONFIG_AMD_ATL */ 55 + 56 + #if defined(CONFIG_ARM) || defined(CONFIG_ARM64) 57 + #include <asm/smp_plat.h> 58 + /* 59 + * Include ARM-specific SMP header which provides a function mapping mpidr to 60 + * CPU logical index. 61 + */ 62 + #define GET_LOGICAL_INDEX(mpidr) get_logical_index(mpidr & MPIDR_HWID_BITMASK) 63 + #else 64 + #define GET_LOGICAL_INDEX(mpidr) -EINVAL 65 + #endif /* CONFIG_ARM || CONFIG_ARM64 */ 54 66 55 67 #endif /* __RAS_H__ */
+44 -5
include/ras/ras_event.h
··· 168 168 * This event is generated when hardware detects an ARM processor error 169 169 * has occurred. UEFI 2.6 spec section N.2.4.4. 170 170 */ 171 + #define APEIL "ARM Processor Err Info data len" 172 + #define APEID "ARM Processor Err Info raw data" 173 + #define APECIL "ARM Processor Err Context Info data len" 174 + #define APECID "ARM Processor Err Context Info raw data" 175 + #define VSEIL "Vendor Specific Err Info data len" 176 + #define VSEID "Vendor Specific Err Info raw data" 171 177 TRACE_EVENT(arm_event, 172 178 173 - TP_PROTO(const struct cper_sec_proc_arm *proc), 179 + TP_PROTO(const struct cper_sec_proc_arm *proc, 180 + const u8 *pei_err, 181 + const u32 pei_len, 182 + const u8 *ctx_err, 183 + const u32 ctx_len, 184 + const u8 *oem, 185 + const u32 oem_len, 186 + u8 sev, 187 + int cpu), 174 188 175 - TP_ARGS(proc), 189 + TP_ARGS(proc, pei_err, pei_len, ctx_err, ctx_len, oem, oem_len, sev, cpu), 176 190 177 191 TP_STRUCT__entry( 178 192 __field(u64, mpidr) ··· 194 180 __field(u32, running_state) 195 181 __field(u32, psci_state) 196 182 __field(u8, affinity) 183 + __field(u32, pei_len) 184 + __dynamic_array(u8, pei_buf, pei_len) 185 + __field(u32, ctx_len) 186 + __dynamic_array(u8, ctx_buf, ctx_len) 187 + __field(u32, oem_len) 188 + __dynamic_array(u8, oem_buf, oem_len) 189 + __field(u8, sev) 190 + __field(int, cpu) 197 191 ), 198 192 199 193 TP_fast_assign( ··· 221 199 __entry->running_state = ~0; 222 200 __entry->psci_state = ~0; 223 201 } 202 + __entry->pei_len = pei_len; 203 + memcpy(__get_dynamic_array(pei_buf), pei_err, pei_len); 204 + __entry->ctx_len = ctx_len; 205 + memcpy(__get_dynamic_array(ctx_buf), ctx_err, ctx_len); 206 + __entry->oem_len = oem_len; 207 + memcpy(__get_dynamic_array(oem_buf), oem, oem_len); 208 + __entry->sev = sev; 209 + __entry->cpu = cpu; 224 210 ), 225 211 226 - TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; " 227 - "running state: %d; PSCI state: %d", 212 + TP_printk("cpu: %d; error: %d; affinity level: %d; MPIDR: %016llx; MIDR: %016llx; " 213 + "running state: %d; PSCI state: %d; " 214 + "%s: %d; %s: %s; %s: %d; %s: %s; %s: %d; %s: %s", 215 + __entry->cpu, 216 + __entry->sev, 228 217 __entry->affinity, __entry->mpidr, __entry->midr, 229 - __entry->running_state, __entry->psci_state) 218 + __entry->running_state, __entry->psci_state, 219 + APEIL, __entry->pei_len, APEID, 220 + __print_hex(__get_dynamic_array(pei_buf), __entry->pei_len), 221 + APECIL, __entry->ctx_len, APECID, 222 + __print_hex(__get_dynamic_array(ctx_buf), __entry->ctx_len), 223 + VSEIL, __entry->oem_len, VSEID, 224 + __print_hex(__get_dynamic_array(oem_buf), __entry->oem_len)) 230 225 ); 231 226 232 227 /*