1/* 2 * Copyright 2012 Intel Corporation 3 * Author: Josh Triplett <josh@joshtriplett.org> 4 * 5 * Based on the bgrt driver: 6 * Copyright 2012 Red Hat, Inc <mjg@redhat.com> 7 * Author: Matthew Garrett 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 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 19struct acpi_table_bgrt *bgrt_tab; 20void *__initdata bgrt_image; 21size_t __initdata bgrt_image_size; 22 23struct bmp_header { 24 u16 id; 25 u32 size; 26} __packed; 27 28void __init efi_bgrt_init(void) 29{ 30 acpi_status status; 31 void __iomem *image; 32 bool ioremapped = false; 33 struct bmp_header bmp_header; 34 35 if (acpi_disabled) 36 return; 37 38 status = acpi_get_table("BGRT", 0, 39 (struct acpi_table_header **)&bgrt_tab); 40 if (ACPI_FAILURE(status)) 41 return; 42 43 if (bgrt_tab->header.length < sizeof(*bgrt_tab)) { 44 pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n", 45 bgrt_tab->header.length, sizeof(*bgrt_tab)); 46 return; 47 } 48 if (bgrt_tab->version != 1) { 49 pr_err("Ignoring BGRT: invalid version %u (expected 1)\n", 50 bgrt_tab->version); 51 return; 52 } 53 if (bgrt_tab->status != 1) { 54 pr_err("Ignoring BGRT: invalid status %u (expected 1)\n", 55 bgrt_tab->status); 56 return; 57 } 58 if (bgrt_tab->image_type != 0) { 59 pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n", 60 bgrt_tab->image_type); 61 return; 62 } 63 if (!bgrt_tab->image_address) { 64 pr_err("Ignoring BGRT: null image address\n"); 65 return; 66 } 67 68 image = efi_lookup_mapped_addr(bgrt_tab->image_address); 69 if (!image) { 70 image = early_ioremap(bgrt_tab->image_address, 71 sizeof(bmp_header)); 72 ioremapped = true; 73 if (!image) { 74 pr_err("Ignoring BGRT: failed to map image header memory\n"); 75 return; 76 } 77 } 78 79 memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); 80 if (ioremapped) 81 early_iounmap(image, sizeof(bmp_header)); 82 bgrt_image_size = bmp_header.size; 83 84 bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN); 85 if (!bgrt_image) { 86 pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n", 87 bgrt_image_size); 88 return; 89 } 90 91 if (ioremapped) { 92 image = early_ioremap(bgrt_tab->image_address, 93 bmp_header.size); 94 if (!image) { 95 pr_err("Ignoring BGRT: failed to map image memory\n"); 96 kfree(bgrt_image); 97 bgrt_image = NULL; 98 return; 99 } 100 } 101 102 memcpy_fromio(bgrt_image, image, bgrt_image_size); 103 if (ioremapped) 104 early_iounmap(image, bmp_header.size); 105} 106