Path: blob/master/drivers/firmware/iscsi_ibft_find.c
15109 views
/*1* Copyright 2007-2010 Red Hat, Inc.2* by Peter Jones <[email protected]>3* Copyright 2007 IBM, Inc.4* by Konrad Rzeszutek <[email protected]>5* Copyright 20086* by Konrad Rzeszutek <[email protected]>7*8* This code finds the iSCSI Boot Format Table.9*10* This program is free software; you can redistribute it and/or modify11* it under the terms of the GNU General Public License v2.0 as published by12* the Free Software Foundation13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*/1920#include <linux/bootmem.h>21#include <linux/blkdev.h>22#include <linux/ctype.h>23#include <linux/device.h>24#include <linux/efi.h>25#include <linux/err.h>26#include <linux/init.h>27#include <linux/limits.h>28#include <linux/module.h>29#include <linux/pci.h>30#include <linux/stat.h>31#include <linux/string.h>32#include <linux/types.h>33#include <linux/acpi.h>34#include <linux/iscsi_ibft.h>3536#include <asm/mmzone.h>3738/*39* Physical location of iSCSI Boot Format Table.40*/41struct acpi_table_ibft *ibft_addr;42EXPORT_SYMBOL_GPL(ibft_addr);4344static const struct {45char *sign;46} ibft_signs[] = {47#ifdef CONFIG_ACPI48/*49* One spec says "IBFT", the other says "iBFT". We have to check50* for both.51*/52{ ACPI_SIG_IBFT },53#endif54{ "iBFT" },55{ "BIFT" }, /* Broadcom iSCSI Offload */56};5758#define IBFT_SIGN_LEN 459#define IBFT_START 0x80000 /* 512kB */60#define IBFT_END 0x100000 /* 1MB */61#define VGA_MEM 0xA0000 /* VGA buffer */62#define VGA_SIZE 0x20000 /* 128kB */6364#ifdef CONFIG_ACPI65static int __init acpi_find_ibft(struct acpi_table_header *header)66{67ibft_addr = (struct acpi_table_ibft *)header;68return 0;69}70#endif /* CONFIG_ACPI */7172static int __init find_ibft_in_mem(void)73{74unsigned long pos;75unsigned int len = 0;76void *virt;77int i;7879for (pos = IBFT_START; pos < IBFT_END; pos += 16) {80/* The table can't be inside the VGA BIOS reserved space,81* so skip that area */82if (pos == VGA_MEM)83pos += VGA_SIZE;84virt = isa_bus_to_virt(pos);8586for (i = 0; i < ARRAY_SIZE(ibft_signs); i++) {87if (memcmp(virt, ibft_signs[i].sign, IBFT_SIGN_LEN) ==880) {89unsigned long *addr =90(unsigned long *)isa_bus_to_virt(pos + 4);91len = *addr;92/* if the length of the table extends past 1M,93* the table cannot be valid. */94if (pos + len <= (IBFT_END-1)) {95ibft_addr = (struct acpi_table_ibft *)virt;96goto done;97}98}99}100}101done:102return len;103}104/*105* Routine used to find the iSCSI Boot Format Table. The logical106* kernel address is set in the ibft_addr global variable.107*/108unsigned long __init find_ibft_region(unsigned long *sizep)109{110#ifdef CONFIG_ACPI111int i;112#endif113ibft_addr = NULL;114115#ifdef CONFIG_ACPI116for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++)117acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft);118#endif /* CONFIG_ACPI */119120/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will121* only use ACPI for this */122123if (!ibft_addr && !efi_enabled)124find_ibft_in_mem();125126if (ibft_addr) {127*sizep = PAGE_ALIGN(ibft_addr->header.length);128return (u64)isa_virt_to_bus(ibft_addr);129}130131*sizep = 0;132return 0;133}134135136