summaryrefslogtreecommitdiff
path: root/src/mainboard/siemens/mc_tcu3/modhwinfo.c
blob: a024095769fd7a9d67d972dade6a01a749860fc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 Siemens AG.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc.
 */

#include "modhwinfo.h"
#include "lcd_panel.h"
#include <cbfs.h>
#include <string.h>

/** \brief This function will find the first linked info block.
 * @param  *filename    Filename in cbfs
 * @param  *file_offset Pointer to the offset of the cbfs file contents
 * @return u8*          Pointer to the found block
 */
u8* get_first_linked_block(char *filename, u8 **file_offset)
{
	u8* block_ptr = NULL;

	block_ptr = cbfs_boot_map_with_leak(filename, 0x50, NULL);
	if (!block_ptr)
		return NULL;
	if (!strncmp((char*)block_ptr, "H1W2M3I4", LEN_MAGIC_NUM)) {
		if ((*((u16*)(block_ptr + HWI_LEN_OFFSET)) == LEN_MAIN_HWINFO) &&
		    (*((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) != 0x00)) {
			*file_offset = block_ptr;
			return *((s32*)(block_ptr + NEXT_OFFSET_HWINFO)) + block_ptr;
		} else
			return NULL;
	} else if (!strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)) {
		*file_offset = block_ptr;
		return block_ptr;
	} else
		return NULL;
}

/** \brief This function will find the main info block
 * @param  *filename Filename in cbfs
 * @return *hwinfo   Pointer to the data of the main info block
 */
struct hwinfo* get_hwinfo(char *filename)
{
	struct hwinfo* main_hwinfo;

	main_hwinfo = cbfs_boot_map_with_leak(filename, 0x50, NULL);
	if ((main_hwinfo) &&
		(!strncmp(main_hwinfo->magicNumber, "H1W2M3I4", LEN_MAGIC_NUM)) &&
		(main_hwinfo->length == LEN_MAIN_HWINFO))
		  return main_hwinfo;
	else
		return NULL;
}

/** \brief This function will find the short info block
 * @param  *filename  Filename in cbfs
 * @return *shortinfo Pointer to the data of the short info block
 */
struct shortinfo* get_shortinfo(char *filename)
{
	u8 *block_ptr = NULL;
	u8 *file_offset = NULL;

	block_ptr = get_first_linked_block(filename, &file_offset);
	if ((block_ptr == NULL) ||
	    (strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)))
		return NULL;

	if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO)
		return (struct shortinfo *)block_ptr;

	block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_EDID)));
	if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_SHORT_INFO)
		return (struct shortinfo *)block_ptr;
	else
		return NULL;
}

/** \brief This function will find the edid info block
 * @param  *filename  Filename in cbfs
 * @return *edidinfo  Pointer to the data of the edid info block
 */
struct edidinfo* get_edidinfo(char *filename)
{
	u8 *block_ptr = NULL;
	u8 *file_offset = NULL;

	block_ptr = get_first_linked_block(filename, &file_offset);
	if ((block_ptr == NULL) ||
	    (strncmp((char*)block_ptr, "H1W2M3I5", LEN_MAGIC_NUM)))
		return NULL;

	if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO)
		return (struct edidinfo *)block_ptr;

	block_ptr = (file_offset + *((s32*)(block_ptr + NEXT_OFFSET_SIB)));
	if ((*((u16*)(block_ptr + HWI_LEN_OFFSET))) == LEN_EDID_INFO)
		return (struct edidinfo *)block_ptr;
	else
		return NULL;
}

/** \brief This function will search for a MAC address which can be assigned
 *         to a MACPHY.
 * @param  pci_bdf Bus, device and function of the given PCI-device
 * @param  mac     buffer where to store the MAC address
 * @return cb_err  CB_ERR or CB_SUCCESS
 */
enum cb_err mainboard_get_mac_address(u16 bus, u8 devfn, u8 mac[6])
{
	struct hwinfo* main_hwinfo;
	u32 i;

	main_hwinfo = get_hwinfo((char*)"hwinfo.hex");
	if (!main_hwinfo)
		return CB_ERR;
	/* Ensure the first MAC-Address is not completely 0x00 or 0xff */
	for (i = 0; i < 6; i++) {
		if (main_hwinfo->macAddress1[i] != 0xFF)
			break;
	}
	if (i == 6){
		return CB_ERR;
	}
	for (i = 0; i < 6; i++) {
		if (main_hwinfo->macAddress1[i] != 0x00)
			break;
	}
	if (i == 6){
		return CB_ERR;
	} else {
		memcpy(mac, main_hwinfo->macAddress1, 6);
		return CB_SUCCESS;
	}
}