Ver código fonte

[pci] Add a mechanism for using a PCI VPD field as an NVS device

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 anos atrás
pai
commit
ce7b0efa87
2 arquivos alterados com 157 adições e 0 exclusões
  1. 124
    0
      src/drivers/nvs/nvsvpd.c
  2. 33
    0
      src/include/ipxe/nvsvpd.h

+ 124
- 0
src/drivers/nvs/nvsvpd.c Ver arquivo

@@ -0,0 +1,124 @@
1
+/*
2
+ * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdio.h>
22
+#include <ipxe/nvs.h>
23
+#include <ipxe/pci.h>
24
+#include <ipxe/pcivpd.h>
25
+#include <ipxe/nvsvpd.h>
26
+
27
+/** @file
28
+ *
29
+ * Non-Volatile Storage using Vital Product Data
30
+ *
31
+ */
32
+
33
+/**
34
+ * Read from VPD
35
+ *
36
+ * @v nvs		NVS device
37
+ * @v address		Starting address
38
+ * @v buf		Data buffer
39
+ * @v len		Length of data buffer
40
+ * @ret rc		Return status code
41
+ */
42
+static int nvs_vpd_read ( struct nvs_device *nvs, unsigned int address,
43
+			  void *data, size_t len ) {
44
+	struct nvs_vpd_device *nvsvpd =
45
+		container_of ( nvs, struct nvs_vpd_device, nvs );
46
+	int rc;
47
+
48
+	if ( ( rc = pci_vpd_read ( &nvsvpd->vpd, ( nvsvpd->address + address ),
49
+				   data, len ) ) != 0 ) {
50
+		DBGC ( nvsvpd->vpd.pci, PCI_FMT " NVS could not read "
51
+		       "[%04x,%04zx): %s\n", PCI_ARGS ( nvsvpd->vpd.pci ),
52
+		       address, ( address + len ), strerror ( rc ) );
53
+		return rc;
54
+	}
55
+
56
+	return 0;
57
+}
58
+
59
+/**
60
+ * Write to VPD
61
+ *
62
+ * @v nvs		NVS device
63
+ * @v address		Starting address
64
+ * @v buf		Data buffer
65
+ * @v len		Length of data buffer
66
+ * @ret rc		Return status code
67
+ */
68
+static int nvs_vpd_write ( struct nvs_device *nvs, unsigned int address,
69
+			   const void *data, size_t len ) {
70
+	struct nvs_vpd_device *nvsvpd =
71
+		container_of ( nvs, struct nvs_vpd_device, nvs );
72
+	int rc;
73
+
74
+	if ( ( rc = pci_vpd_write ( &nvsvpd->vpd, ( nvsvpd->address + address ),
75
+				    data, len ) ) != 0 ) {
76
+		DBGC ( nvsvpd->vpd.pci, PCI_FMT " NVS could not write "
77
+		       "[%04x,%04zx): %s\n", PCI_ARGS ( nvsvpd->vpd.pci ),
78
+		       address, ( address + len ), strerror ( rc ) );
79
+		return rc;
80
+	}
81
+
82
+	return 0;
83
+}
84
+
85
+/**
86
+ * Initialise NVS VPD device
87
+ *
88
+ * @v nvsvpd		NVS VPD device
89
+ * @v pci		PCI device
90
+ * @ret rc		Return status code
91
+ */
92
+int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci,
93
+		   unsigned int field ) {
94
+	size_t len;
95
+	int rc;
96
+
97
+	/* Initialise VPD device */
98
+	if ( ( rc = pci_vpd_init ( &nvsvpd->vpd, pci ) ) != 0 ) {
99
+		DBGC ( pci, PCI_FMT " NVS could not initialise "
100
+		       "VPD: %s\n", PCI_ARGS ( pci ), strerror ( rc ) );
101
+		return rc;
102
+	}
103
+
104
+	/* Locate VPD field */
105
+	if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &nvsvpd->address,
106
+				   &len ) ) != 0 ) {
107
+		DBGC ( pci, PCI_FMT " NVS could not locate VPD field "
108
+		       PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
109
+		       PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
110
+		return rc;
111
+	}
112
+
113
+	/* Initialise NVS device */
114
+	nvsvpd->nvs.block_size = 1;
115
+	nvsvpd->nvs.size = len;
116
+	nvsvpd->nvs.read = nvs_vpd_read;
117
+	nvsvpd->nvs.write = nvs_vpd_write;
118
+
119
+	DBGC ( pci, PCI_FMT " NVS using VPD field " PCI_VPD_FIELD_FMT " at "
120
+	       "[%04x,%04x)\n", PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
121
+	       nvsvpd->address, ( nvsvpd->address + nvsvpd->nvs.size ) );
122
+
123
+	return 0;
124
+}

+ 33
- 0
src/include/ipxe/nvsvpd.h Ver arquivo

@@ -0,0 +1,33 @@
1
+#ifndef _IPXE_NVSVPD_H
2
+#define _IPXE_NVSVPD_H
3
+
4
+/**
5
+ * @file
6
+ *
7
+ * Non-Volatile Storage using Vital Product Data
8
+ *
9
+ */
10
+
11
+FILE_LICENCE ( GPL2_OR_LATER );
12
+
13
+#include <ipxe/nvs.h>
14
+#include <ipxe/pcivpd.h>
15
+
16
+/** An NVS VPD device */
17
+struct nvs_vpd_device {
18
+	/** NVS device */
19
+	struct nvs_device nvs;
20
+	/** PCI VPD device */
21
+	struct pci_vpd vpd;
22
+	/** Starting address
23
+	 *
24
+	 * This address is added to the NVS address to form the VPD
25
+	 * address.
26
+	 */
27
+	unsigned int address;
28
+};
29
+
30
+extern int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci,
31
+			  unsigned int field );
32
+
33
+#endif /* IPXE_NVSVPD_H */

Carregando…
Cancelar
Salvar