|
@@ -1,5 +1,5 @@
|
1
|
1
|
/*
|
2
|
|
- * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
|
|
2
|
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
|
3
|
3
|
*
|
4
|
4
|
* This program is free software; you can redistribute it and/or
|
5
|
5
|
* modify it under the terms of the GNU General Public License as
|
|
@@ -13,25 +13,103 @@
|
13
|
13
|
*
|
14
|
14
|
* You should have received a copy of the GNU General Public License
|
15
|
15
|
* along with this program; if not, write to the Free Software
|
16
|
|
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
16
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
17
|
+ * 02110-1301, USA.
|
17
|
18
|
*/
|
18
|
19
|
|
19
|
|
-FILE_LICENCE(GPL2_OR_LATER);
|
|
20
|
+FILE_LICENCE ( GPL2_OR_LATER );
|
20
|
21
|
|
21
|
22
|
#include <errno.h>
|
|
23
|
+#include <linux_api.h>
|
|
24
|
+#include <ipxe/linux.h>
|
22
|
25
|
#include <ipxe/smbios.h>
|
23
|
26
|
|
|
27
|
+/** SMBIOS filename */
|
|
28
|
+static const char smbios_filename[] = "/dev/mem";
|
|
29
|
+
|
|
30
|
+/** SMBIOS entry point scan region start address */
|
|
31
|
+#define SMBIOS_ENTRY_START 0xf0000
|
|
32
|
+
|
|
33
|
+/** SMBIOS entry point scan region length */
|
|
34
|
+#define SMBIOS_ENTRY_LEN 0x10000
|
|
35
|
+
|
|
36
|
+/** SMBIOS mapping alignment */
|
|
37
|
+#define SMBIOS_ALIGN 0x1000
|
|
38
|
+
|
24
|
39
|
/**
|
25
|
40
|
* Find SMBIOS
|
26
|
41
|
*
|
27
|
|
- * Not implemented currently.
|
28
|
|
- *
|
29
|
42
|
* @v smbios SMBIOS entry point descriptor structure to fill in
|
30
|
43
|
* @ret rc Return status code
|
31
|
44
|
*/
|
32
|
|
-static int linux_find_smbios(struct smbios *smbios __unused)
|
33
|
|
-{
|
34
|
|
- return -ENODEV;
|
|
45
|
+static int linux_find_smbios ( struct smbios *smbios ) {
|
|
46
|
+ struct smbios_entry entry;
|
|
47
|
+ void *entry_mem;
|
|
48
|
+ void *smbios_mem;
|
|
49
|
+ size_t smbios_offset;
|
|
50
|
+ size_t smbios_indent;
|
|
51
|
+ size_t smbios_len;
|
|
52
|
+ int fd;
|
|
53
|
+ int rc;
|
|
54
|
+
|
|
55
|
+ /* Open SMBIOS file */
|
|
56
|
+ fd = linux_open ( smbios_filename, O_RDONLY );
|
|
57
|
+ if ( fd < 0 ) {
|
|
58
|
+ rc = -ELINUX ( linux_errno );
|
|
59
|
+ DBGC ( smbios, "SMBIOS could not open %s: %s\n",
|
|
60
|
+ smbios_filename, linux_strerror ( linux_errno ) );
|
|
61
|
+ goto err_open;
|
|
62
|
+ }
|
|
63
|
+
|
|
64
|
+ /* Map the region potentially containing the SMBIOS entry point */
|
|
65
|
+ entry_mem = linux_mmap ( NULL, SMBIOS_ENTRY_LEN, PROT_READ, MAP_SHARED,
|
|
66
|
+ fd, SMBIOS_ENTRY_START );
|
|
67
|
+ if ( entry_mem == MAP_FAILED ) {
|
|
68
|
+ rc = -ELINUX ( linux_errno );
|
|
69
|
+ DBGC ( smbios, "SMBIOS could not mmap %s (%#x+%#x): %s\n",
|
|
70
|
+ smbios_filename, SMBIOS_ENTRY_START, SMBIOS_ENTRY_LEN,
|
|
71
|
+ linux_strerror ( linux_errno ) );
|
|
72
|
+ goto err_mmap_entry;
|
|
73
|
+ }
|
|
74
|
+
|
|
75
|
+ /* Scan for the SMBIOS entry point */
|
|
76
|
+ if ( ( rc = find_smbios_entry ( virt_to_user ( entry_mem ),
|
|
77
|
+ SMBIOS_ENTRY_LEN, &entry ) ) != 0 )
|
|
78
|
+ goto err_find_entry;
|
|
79
|
+
|
|
80
|
+ /* Map the region containing the SMBIOS structures */
|
|
81
|
+ smbios_indent = ( entry.smbios_address & ( SMBIOS_ALIGN - 1 ) );
|
|
82
|
+ smbios_offset = ( entry.smbios_address - smbios_indent );
|
|
83
|
+ smbios_len = ( entry.smbios_len + smbios_indent );
|
|
84
|
+ smbios_mem = linux_mmap ( NULL, smbios_len, PROT_READ, MAP_SHARED,
|
|
85
|
+ fd, smbios_offset );
|
|
86
|
+ if ( smbios_mem == MAP_FAILED ) {
|
|
87
|
+ rc = -ELINUX ( linux_errno );
|
|
88
|
+ DBGC ( smbios, "SMBIOS could not mmap %s (%#zx+%#zx): %s\n",
|
|
89
|
+ smbios_filename, smbios_offset, smbios_len,
|
|
90
|
+ linux_strerror ( linux_errno ) );
|
|
91
|
+ goto err_mmap_smbios;
|
|
92
|
+ }
|
|
93
|
+
|
|
94
|
+ /* Fill in entry point descriptor structure */
|
|
95
|
+ smbios->address = virt_to_user ( smbios_mem + smbios_indent );
|
|
96
|
+ smbios->len = entry.smbios_len;
|
|
97
|
+ smbios->count = entry.smbios_count;
|
|
98
|
+ smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
|
|
99
|
+
|
|
100
|
+ /* Unmap the entry point region (no longer required) */
|
|
101
|
+ linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN );
|
|
102
|
+
|
|
103
|
+ return 0;
|
|
104
|
+
|
|
105
|
+ linux_munmap ( smbios_mem, smbios_len );
|
|
106
|
+ err_mmap_smbios:
|
|
107
|
+ err_find_entry:
|
|
108
|
+ linux_munmap ( entry_mem, SMBIOS_ENTRY_LEN );
|
|
109
|
+ err_mmap_entry:
|
|
110
|
+ linux_close ( fd );
|
|
111
|
+ err_open:
|
|
112
|
+ return rc;
|
35
|
113
|
}
|
36
|
114
|
|
37
|
|
-PROVIDE_SMBIOS(linux, find_smbios, linux_find_smbios);
|
|
115
|
+PROVIDE_SMBIOS ( linux, find_smbios, linux_find_smbios );
|