Werner Zeh | c42a613 | 2015-02-12 12:40:15 +0100 | [diff] [blame^] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2014 Siemens AG. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ |
| 19 | |
| 20 | #include "modhwinfo.h" |
| 21 | #include "lcd_panel.h" |
| 22 | #include <cbfs.h> |
| 23 | #include <string.h> |
| 24 | |
| 25 | /** \brief This function will find the first linked info block. |
| 26 | * @param *filename Filename in cbfs |
| 27 | * @param *file_offset Pointer to the offset of the cbfs file contents |
| 28 | * @return u8* Pointer to the found block |
| 29 | */ |
| 30 | u8* get_first_linked_block(char *filename, u8 **file_offset) |
| 31 | { |
| 32 | u8* block_ptr = NULL; |
| 33 | |
| 34 | block_ptr = (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, filename, |
| 35 | 0x50, NULL)); |
| 36 | if (!block_ptr) |
| 37 | return NULL; |
| 38 | if (!strncmp((char*)block_ptr, "H1W2M3I4", LEN_MAGIC_NUM)) { |
| 39 | if ((*((u16*)(block_ptr + HWI_LEN_OFFSET)) == LEN_MAIN_HWINFO) && |
| 40 | (*((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) != 0x00)) { |
| 41 | *file_offset = block_ptr; |
| 42 | return *((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) + block_ptr; |
| 43 | } else |
| 44 | return NULL; |
| 45 | } else if (!strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)) { |
| 46 | *file_offset = block_ptr; |
| 47 | return block_ptr; |
| 48 | } else |
| 49 | return NULL; |
| 50 | } |
| 51 | |
| 52 | /** \brief This function will find the main info block |
| 53 | * @param *filename Filename in cbfs |
| 54 | * @return *hwinfo Pointer to the data of the main info block |
| 55 | */ |
| 56 | struct hwinfo* get_hwinfo(char *filename) |
| 57 | { |
| 58 | struct hwinfo* main_hwinfo; |
| 59 | |
| 60 | main_hwinfo = (struct hwinfo*)(cbfs_get_file_content(CBFS_DEFAULT_MEDIA, |
| 61 | filename, 0x50, NULL)); |
| 62 | if ((main_hwinfo) && |
| 63 | (!strncmp(main_hwinfo->magicNumber, "H1W2M3I4", LEN_MAGIC_NUM)) && |
| 64 | (main_hwinfo->length == LEN_MAIN_HWINFO)) |
| 65 | return main_hwinfo; |
| 66 | else |
| 67 | return NULL; |
| 68 | } |
| 69 | |
| 70 | /** \brief This function will find the short info block |
| 71 | * @param *filename Filename in cbfs |
| 72 | * @return *shortinfo Pointer to the data of the short info block |
| 73 | */ |
| 74 | struct shortinfo* get_shortinfo(char *filename) |
| 75 | { |
| 76 | u8 *block_ptr = NULL; |
| 77 | u8 *file_offset = NULL; |
| 78 | |
| 79 | block_ptr = get_first_linked_block(filename, &file_offset); |
| 80 | if ((block_ptr == NULL) || |
| 81 | (strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM))) |
| 82 | return NULL; |
| 83 | |
| 84 | if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO) |
| 85 | return (struct shortinfo *)block_ptr; |
| 86 | |
| 87 | block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_EDID))); |
| 88 | if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO) |
| 89 | return (struct shortinfo *)block_ptr; |
| 90 | else |
| 91 | return NULL; |
| 92 | } |
| 93 | |
| 94 | /** \brief This function will find the edid info block |
| 95 | * @param *filename Filename in cbfs |
| 96 | * @return *edidinfo Pointer to the data of the edid info block |
| 97 | */ |
| 98 | struct edidinfo* get_edidinfo(char *filename) |
| 99 | { |
| 100 | u8 *block_ptr = NULL; |
| 101 | u8 *file_offset = NULL; |
| 102 | |
| 103 | block_ptr = get_first_linked_block(filename, &file_offset); |
| 104 | if ((block_ptr == NULL) || |
| 105 | (strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM))) |
| 106 | return NULL; |
| 107 | |
| 108 | if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO) |
| 109 | return (struct edidinfo *)block_ptr; |
| 110 | |
| 111 | block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_SIB))); |
| 112 | if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO) |
| 113 | return (struct edidinfo *)block_ptr; |
| 114 | else |
| 115 | return NULL; |
| 116 | } |
| 117 | |
| 118 | /** \brief This function will search for a MAC address which can be assigned |
| 119 | * to a MACPHY. |
| 120 | * @param pci_bdf Bus, device and function of the given PCI-device |
| 121 | * @param mac buffer where to store the MAC address |
| 122 | * @return cb_err CB_ERR or CB_SUCCESS |
| 123 | */ |
| 124 | enum cb_err mainboard_get_mac_address(u16 bus, u8 devfn, u8 mac[6]) |
| 125 | { |
| 126 | struct hwinfo* main_hwinfo; |
| 127 | u32 i; |
| 128 | |
| 129 | main_hwinfo = get_hwinfo((char*)"hwinfo.hex"); |
| 130 | if (!main_hwinfo) |
| 131 | return CB_ERR; |
| 132 | /* Ensure the first MAC-Address is not completely 0x00 or 0xff */ |
| 133 | for (i = 0; i < 6; i++) { |
| 134 | if (main_hwinfo->macAddress1[i] != 0xFF) |
| 135 | break; |
| 136 | } |
| 137 | if (i == 6){ |
| 138 | return CB_ERR; |
| 139 | } |
| 140 | for (i = 0; i < 6; i++) { |
| 141 | if (main_hwinfo->macAddress1[i] != 0x00) |
| 142 | break; |
| 143 | } |
| 144 | if (i == 6){ |
| 145 | return CB_ERR; |
| 146 | } else { |
| 147 | memcpy(mac, main_hwinfo->macAddress1, 6); |
| 148 | return CB_SUCCESS; |
| 149 | } |
| 150 | } |