1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2012 Intel Corporation |
4 | * Author: Josh Triplett <josh@joshtriplett.org> |
5 | * |
6 | * Based on the bgrt driver: |
7 | * Copyright 2012 Red Hat, Inc <mjg@redhat.com> |
8 | * Author: Matthew Garrett |
9 | */ |
10 | |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
12 | |
13 | #include <linux/kernel.h> |
14 | #include <linux/init.h> |
15 | #include <linux/acpi.h> |
16 | #include <linux/efi.h> |
17 | #include <linux/efi-bgrt.h> |
18 | |
19 | struct acpi_table_bgrt bgrt_tab; |
20 | size_t bgrt_image_size; |
21 | |
22 | struct { |
23 | u16 ; |
24 | u32 ; |
25 | } __packed; |
26 | |
27 | void __init efi_bgrt_init(struct acpi_table_header *table) |
28 | { |
29 | void *image; |
30 | struct bmp_header ; |
31 | struct acpi_table_bgrt *bgrt = &bgrt_tab; |
32 | |
33 | if (acpi_disabled) |
34 | return; |
35 | |
36 | if (!efi_enabled(EFI_MEMMAP)) |
37 | return; |
38 | |
39 | if (table->length < sizeof(bgrt_tab)) { |
40 | pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n" , |
41 | table->length, sizeof(bgrt_tab)); |
42 | return; |
43 | } |
44 | *bgrt = *(struct acpi_table_bgrt *)table; |
45 | /* |
46 | * Only version 1 is defined but some older laptops (seen on Lenovo |
47 | * Ivy Bridge models) have a correct version 1 BGRT table with the |
48 | * version set to 0, so we accept version 0 and 1. |
49 | */ |
50 | if (bgrt->version > 1) { |
51 | pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n" , |
52 | bgrt->version); |
53 | goto out; |
54 | } |
55 | if (bgrt->image_type != 0) { |
56 | pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n" , |
57 | bgrt->image_type); |
58 | goto out; |
59 | } |
60 | if (!bgrt->image_address) { |
61 | pr_notice("Ignoring BGRT: null image address\n" ); |
62 | goto out; |
63 | } |
64 | |
65 | if (efi_mem_type(phys_addr: bgrt->image_address) != EFI_BOOT_SERVICES_DATA) { |
66 | pr_notice("Ignoring BGRT: invalid image address\n" ); |
67 | goto out; |
68 | } |
69 | image = early_memremap(phys_addr: bgrt->image_address, size: sizeof(bmp_header)); |
70 | if (!image) { |
71 | pr_notice("Ignoring BGRT: failed to map image header memory\n" ); |
72 | goto out; |
73 | } |
74 | |
75 | memcpy(&bmp_header, image, sizeof(bmp_header)); |
76 | early_memunmap(addr: image, size: sizeof(bmp_header)); |
77 | if (bmp_header.id != 0x4d42) { |
78 | pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n" , |
79 | bmp_header.id); |
80 | goto out; |
81 | } |
82 | bgrt_image_size = bmp_header.size; |
83 | efi_mem_reserve(addr: bgrt->image_address, size: bgrt_image_size); |
84 | |
85 | return; |
86 | out: |
87 | memset(bgrt, 0, sizeof(bgrt_tab)); |
88 | } |
89 | |