iPXE
nvsvpd.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdio.h>
27#include <string.h>
28#include <errno.h>
29#include <ipxe/nvs.h>
30#include <ipxe/pci.h>
31#include <ipxe/pcivpd.h>
32#include <ipxe/nvo.h>
33#include <ipxe/nvsvpd.h>
34
35/** @file
36 *
37 * Non-Volatile Storage using Vital Product Data
38 *
39 */
40
41/**
42 * Read from VPD field
43 *
44 * @v nvs NVS device
45 * @v field VPD field descriptor
46 * @v data Data buffer
47 * @v len Length of data buffer
48 * @ret rc Return status code
49 */
50static int nvs_vpd_read ( struct nvs_device *nvs, unsigned int field,
51 void *data, size_t len ) {
52 struct nvs_vpd_device *nvsvpd =
54 struct pci_device *pci = nvsvpd->vpd.pci;
55 unsigned int address;
56 size_t max_len;
57 int rc;
58
59 /* Allow reading non-existent field */
60 if ( len == 0 )
61 return 0;
62
63 /* Locate VPD field */
64 if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
65 &max_len ) ) != 0 ) {
66 DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
67 PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
68 PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
69 return rc;
70 }
71
72 /* Sanity check */
73 if ( len > max_len ) {
74 DBGC ( pci, PCI_FMT " NVS VPD cannot read %#02zx bytes "
75 "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
76 PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
77 address, ( address + max_len ) );
78 return -ENXIO;
79 }
80
81 /* Read from VPD field */
82 if ( ( rc = pci_vpd_read ( &nvsvpd->vpd, address, data, len ) ) != 0 ) {
83 DBGC ( pci, PCI_FMT " NVS VPD could not read field "
84 PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
85 PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
86 address, ( address + len ), strerror ( rc ) );
87 return rc;
88 }
89
90 return 0;
91}
92
93/**
94 * Write to VPD field
95 *
96 * @v nvs NVS device
97 * @v field VPD field descriptor
98 * @v data Data buffer
99 * @v len Length of data buffer
100 * @ret rc Return status code
101 */
102static int nvs_vpd_write ( struct nvs_device *nvs, unsigned int field,
103 const void *data, size_t len ) {
104 struct nvs_vpd_device *nvsvpd =
105 container_of ( nvs, struct nvs_vpd_device, nvs );
106 struct pci_device *pci = nvsvpd->vpd.pci;
107 unsigned int address;
108 size_t max_len;
109 int rc;
110
111 /* Locate VPD field */
112 if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
113 &max_len ) ) != 0 ) {
114 DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
115 PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
116 PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
117 return rc;
118 }
119
120 /* Sanity check */
121 if ( len > max_len ) {
122 DBGC ( pci, PCI_FMT " NVS VPD cannot write %#02zx bytes "
123 "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
124 PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
125 address, ( address + max_len ) );
126 return -ENXIO;
127 }
128
129 /* Write field */
130 if ( ( rc = pci_vpd_write ( &nvsvpd->vpd, address, data,
131 len ) ) != 0 ) {
132 DBGC ( pci, PCI_FMT " NVS VPD could not write field "
133 PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
134 PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
135 address, ( address + len ), strerror ( rc ) );
136 return rc;
137 }
138
139 return 0;
140}
141
142/**
143 * Resize VPD field
144 *
145 * @v nvs NVS device
146 * @v field VPD field descriptor
147 * @v data Data buffer
148 * @v len Length of data buffer
149 * @ret rc Return status code
150 */
151static int nvs_vpd_resize ( struct nvs_device *nvs, unsigned int field,
152 size_t len ) {
153 struct nvs_vpd_device *nvsvpd =
154 container_of ( nvs, struct nvs_vpd_device, nvs );
155 struct pci_device *pci = nvsvpd->vpd.pci;
156 unsigned int address;
157 int rc;
158
159 /* Resize field */
160 if ( ( rc = pci_vpd_resize ( &nvsvpd->vpd, field, len,
161 &address ) ) != 0 ) {
162 DBGC ( pci, PCI_FMT " NVS VPD could not resize field "
163 PCI_VPD_FIELD_FMT " to %#02zx bytes: %s\n",
164 PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
165 len, strerror ( rc ) );
166 return rc;
167 }
168
169 return 0;
170}
171
172/**
173 * Initialise NVS VPD device
174 *
175 * @v nvsvpd NVS VPD device
176 * @v pci PCI device
177 * @ret rc Return status code
178 */
179int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci ) {
180 int rc;
181
182 /* Initialise VPD device */
183 if ( ( rc = pci_vpd_init ( &nvsvpd->vpd, pci ) ) != 0 ) {
184 DBGC ( pci, PCI_FMT " NVS could not initialise "
185 "VPD: %s\n", PCI_ARGS ( pci ), strerror ( rc ) );
186 return rc;
187 }
188
189 /* Initialise NVS device */
190 nvsvpd->nvs.read = nvs_vpd_read;
191 nvsvpd->nvs.write = nvs_vpd_write;
192
193 return 0;
194}
195
196/**
197 * Resize non-volatile option storage within NVS VPD device
198 *
199 * @v nvo Non-volatile options block
200 * @v len New length
201 * @ret rc Return status code
202 */
203static int nvs_vpd_nvo_resize ( struct nvo_block *nvo, size_t len ) {
204 int rc;
205
206 /* Resize VPD field */
207 if ( ( rc = nvs_vpd_resize ( nvo->nvs, nvo->address, len ) ) != 0 )
208 return rc;
209
210 return 0;
211}
212
213/**
214 * Initialise non-volatile option storage within NVS VPD device
215 *
216 * @v nvsvpd NVS VPD device
217 * @v field VPD field descriptor
218 * @v nvo Non-volatile options block
219 * @v refcnt Containing object reference counter, or NULL
220 */
221void nvs_vpd_nvo_init ( struct nvs_vpd_device *nvsvpd, unsigned int field,
222 struct nvo_block *nvo, struct refcnt *refcnt ) {
223 struct pci_device *pci = nvsvpd->vpd.pci;
224 unsigned int address;
225 size_t len;
226 int rc;
227
228 /* Locate VPD field, if present */
229 if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
230 &len ) ) != 0 ) {
231 DBGC ( pci, PCI_FMT " NVS VPD field " PCI_VPD_FIELD_FMT
232 " not present; assuming empty\n",
233 PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ) );
234 len = 0;
235 }
236
237 /* Initialise non-volatile options block */
238 nvo_init ( nvo, &nvsvpd->nvs, field, len, nvs_vpd_nvo_resize, refcnt );
239}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint64_t address
Base address.
Definition ena.h:13
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENXIO
No such device or address.
Definition errno.h:600
String functions.
void nvo_init(struct nvo_block *nvo, struct nvs_device *nvs, size_t address, size_t len, int(*resize)(struct nvo_block *nvo, size_t len), struct refcnt *refcnt)
Initialise non-volatile stored options.
Definition nvo.c:274
Non-volatile stored options.
Non-volatile storage.
static int nvs_vpd_resize(struct nvs_device *nvs, unsigned int field, size_t len)
Resize VPD field.
Definition nvsvpd.c:151
void nvs_vpd_nvo_init(struct nvs_vpd_device *nvsvpd, unsigned int field, struct nvo_block *nvo, struct refcnt *refcnt)
Initialise non-volatile option storage within NVS VPD device.
Definition nvsvpd.c:221
static int nvs_vpd_nvo_resize(struct nvo_block *nvo, size_t len)
Resize non-volatile option storage within NVS VPD device.
Definition nvsvpd.c:203
int nvs_vpd_init(struct nvs_vpd_device *nvsvpd, struct pci_device *pci)
Initialise NVS VPD device.
Definition nvsvpd.c:179
static int nvs_vpd_write(struct nvs_device *nvs, unsigned int field, const void *data, size_t len)
Write to VPD field.
Definition nvsvpd.c:102
static int nvs_vpd_read(struct nvs_device *nvs, unsigned int field, void *data, size_t len)
Read from VPD field.
Definition nvsvpd.c:50
Non-Volatile Storage using Vital Product Data.
PCI bus.
#define PCI_FMT
PCI device debug message format.
Definition pci.h:312
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition pci.h:315
int pci_vpd_read(struct pci_vpd *vpd, unsigned int address, void *buf, size_t len)
Read PCI VPD.
Definition pcivpd.c:183
int pci_vpd_resize(struct pci_vpd *vpd, unsigned int field, size_t len, unsigned int *address)
Resize VPD field.
Definition pcivpd.c:411
int pci_vpd_write(struct pci_vpd *vpd, unsigned int address, const void *buf, size_t len)
Write PCI VPD.
Definition pcivpd.c:225
int pci_vpd_find(struct pci_vpd *vpd, unsigned int field, unsigned int *address, size_t *len)
Locate PCI VPD field.
Definition pcivpd.c:353
int pci_vpd_init(struct pci_vpd *vpd, struct pci_device *pci)
Initialise PCI Vital Product Data.
Definition pcivpd.c:48
PCI Vital Product Data.
#define PCI_VPD_FIELD_ARGS(field)
PCI VPD field debug message arguments.
Definition pcivpd.h:73
#define PCI_VPD_FIELD_FMT
PCI VPD field debug message format.
Definition pcivpd.h:70
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A block of non-volatile stored options.
Definition nvo.h:23
unsigned int address
Address within NVS device.
Definition nvo.h:29
struct nvs_device * nvs
Underlying non-volatile storage device.
Definition nvo.h:27
A non-volatile storage device.
Definition nvs.h:16
int(* read)(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read data from device.
Definition nvs.h:48
int(* write)(struct nvs_device *nvs, unsigned int address, const void *data, size_t len)
Write data to device.
Definition nvs.h:60
An NVS VPD device.
Definition nvsvpd.h:20
struct pci_vpd vpd
PCI VPD device.
Definition nvsvpd.h:24
struct nvs_device nvs
NVS device.
Definition nvsvpd.h:22
A PCI device.
Definition pci.h:211
struct pci_device * pci
PCI device.
Definition pcivpd.h:132
A reference counter.
Definition refcnt.h:27