iPXE
Data Structures | Macros | Functions
pcivpd.h File Reference

PCI Vital Product Data. More...

#include <stdint.h>
#include <byteswap.h>
#include <ipxe/isapnp.h>
#include <ipxe/pci.h>

Go to the source code of this file.

Data Structures

struct  pci_vpd_field
 A PCI VPD field. More...
 
struct  pci_vpd_cache
 PCI VPD cache. More...
 
struct  pci_vpd
 PCI VPD. More...
 

Macros

#define PCI_VPD_ADDRESS   0x02
 PCI VPD address register. More...
 
#define PCI_VPD_FLAG   0x8000
 PCI VPD write flag. More...
 
#define PCI_VPD_DATA   0x04
 PCI VPD data register. More...
 
#define PCI_VPD_MAX_LEN   0xff
 Maximum PCI VPD field length. More...
 
#define PCI_VPD_FIELD(tag, keyword1, keyword2)   ( ( (tag) << 16 ) | ( (keyword2) << 8 ) | ( (keyword1) << 0 ) )
 Construct PCI VPD field descriptor. More...
 
#define PCI_VPD_WHOLE_TAG_FIELD(tag)   PCI_VPD_FIELD ( (tag), '\0', '\0' )
 Construct PCI VPD whole-tag field descriptor. More...
 
#define PCI_VPD_TAG(field)   ( (field) >> 16 )
 Extract PCI VPD ISAPnP tag. More...
 
#define PCI_VPD_KEYWORD(field)   ( cpu_to_le16 ( (field) & 0xffff ) )
 Extract PCI VPD keyword. More...
 
#define PCI_VPD_FIELD_FMT   "%c%c"
 PCI VPD field debug message format. More...
 
#define PCI_VPD_FIELD_ARGS(field)   ( (field) >> 0 ), ( (field) >> 8 )
 PCI VPD field debug message arguments. More...
 
#define PCI_VPD_TAG_RO   0x90
 PCI VPD Read-Only field tag. More...
 
#define PCI_VPD_TAG_RW   0x91
 PCI VPD Read-Write field tag. More...
 
#define PCI_VPD_FIELD_NAME   PCI_VPD_WHOLE_TAG_FIELD ( ISAPNP_TAG_ANSISTR )
 PCI VPD Card Name field descriptor. More...
 
#define PCI_VPD_FIELD_PN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'N' )
 PCI VPD Part Number field descriptor. More...
 
#define PCI_VPD_FIELD_EC   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'E', 'C' )
 PCI VPD Engineering Change Level field descriptor. More...
 
#define PCI_VPD_FIELD_FG   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'F', 'G' )
 PCI VPD Fabric Geography field descriptor. More...
 
#define PCI_VPD_FIELD_LC   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'L', 'C' )
 PCI VPD Location field descriptor. More...
 
#define PCI_VPD_FIELD_MN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'M', 'N' )
 PCI VPD Manufacturer ID field descriptor. More...
 
#define PCI_VPD_FIELD_PG   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'G' )
 PCI VPD PCI Geography field descriptor. More...
 
#define PCI_VPD_FIELD_SN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'S', 'N' )
 PCI VPD Serial Number field descriptor. More...
 
#define PCI_VPD_FIELD_CP   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'C', 'P' )
 PCI VPD Extended Capability field descriptor. More...
 
#define PCI_VPD_FIELD_RV   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'R', 'V' )
 PCI VPD Checksum and Reserved field descriptor. More...
 
#define PCI_VPD_FIELD_YA   PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'Y', 'A' )
 PCI VPD Asset Tag field descriptor. More...
 
#define PCI_VPD_FIELD_RW   PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'R', 'W' )
 PCI VPD Remaining Read/Write Area field descriptor. More...
 
#define PCI_VPD_MAX_WAIT_MS   100
 Maximum wait for PCI VPD (in ms) More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static int pci_vpd_is_present (struct pci_vpd *vpd)
 Check for presence of PCI VPD. More...
 
static int pci_vpd_cache_is_valid (struct pci_vpd *vpd)
 Check if PCI VPD read cache is valid. More...
 
static void pci_vpd_invalidate_cache (struct pci_vpd *vpd)
 Invalidate PCI VPD read cache. More...
 
int pci_vpd_init (struct pci_vpd *vpd, struct pci_device *pci)
 Initialise PCI Vital Product Data. More...
 
int pci_vpd_read (struct pci_vpd *vpd, unsigned int address, void *buf, size_t len)
 Read PCI VPD. More...
 
int pci_vpd_write (struct pci_vpd *vpd, unsigned int address, const void *buf, size_t len)
 Write PCI VPD. More...
 
int pci_vpd_find (struct pci_vpd *vpd, unsigned int field, unsigned int *address, size_t *len)
 Locate PCI VPD field. More...
 
int pci_vpd_resize (struct pci_vpd *vpd, unsigned int field, size_t len, unsigned int *address)
 Resize VPD field. More...
 

Detailed Description

PCI Vital Product Data.

Definition in file pcivpd.h.

Macro Definition Documentation

◆ PCI_VPD_ADDRESS

#define PCI_VPD_ADDRESS   0x02

PCI VPD address register.

Definition at line 19 of file pcivpd.h.

◆ PCI_VPD_FLAG

#define PCI_VPD_FLAG   0x8000

PCI VPD write flag.

Definition at line 22 of file pcivpd.h.

◆ PCI_VPD_DATA

#define PCI_VPD_DATA   0x04

PCI VPD data register.

Definition at line 25 of file pcivpd.h.

◆ PCI_VPD_MAX_LEN

#define PCI_VPD_MAX_LEN   0xff

Maximum PCI VPD field length.

Definition at line 36 of file pcivpd.h.

◆ PCI_VPD_FIELD

#define PCI_VPD_FIELD (   tag,
  keyword1,
  keyword2 
)    ( ( (tag) << 16 ) | ( (keyword2) << 8 ) | ( (keyword1) << 0 ) )

Construct PCI VPD field descriptor.

Parameters
tagISAPnP tag
keyword1First character of keyword
keyword2Second character of keyword
Return values
fieldVPD field descriptor

Definition at line 45 of file pcivpd.h.

◆ PCI_VPD_WHOLE_TAG_FIELD

#define PCI_VPD_WHOLE_TAG_FIELD (   tag)    PCI_VPD_FIELD ( (tag), '\0', '\0' )

Construct PCI VPD whole-tag field descriptor.

Parameters
tagISAPnP tag
Return values
fieldVPD field descriptor

Definition at line 53 of file pcivpd.h.

◆ PCI_VPD_TAG

#define PCI_VPD_TAG (   field)    ( (field) >> 16 )

Extract PCI VPD ISAPnP tag.

Parameters
fieldVPD field descriptor
Return values
tagISAPnP tag

Definition at line 60 of file pcivpd.h.

◆ PCI_VPD_KEYWORD

#define PCI_VPD_KEYWORD (   field)    ( cpu_to_le16 ( (field) & 0xffff ) )

Extract PCI VPD keyword.

Parameters
fieldVPD field descriptor
Return values
keywordKeyword

Definition at line 67 of file pcivpd.h.

◆ PCI_VPD_FIELD_FMT

#define PCI_VPD_FIELD_FMT   "%c%c"

PCI VPD field debug message format.

Definition at line 70 of file pcivpd.h.

◆ PCI_VPD_FIELD_ARGS

#define PCI_VPD_FIELD_ARGS (   field)    ( (field) >> 0 ), ( (field) >> 8 )

PCI VPD field debug message arguments.

Definition at line 73 of file pcivpd.h.

◆ PCI_VPD_TAG_RO

#define PCI_VPD_TAG_RO   0x90

PCI VPD Read-Only field tag.

Definition at line 77 of file pcivpd.h.

◆ PCI_VPD_TAG_RW

#define PCI_VPD_TAG_RW   0x91

PCI VPD Read-Write field tag.

Definition at line 80 of file pcivpd.h.

◆ PCI_VPD_FIELD_NAME

#define PCI_VPD_FIELD_NAME   PCI_VPD_WHOLE_TAG_FIELD ( ISAPNP_TAG_ANSISTR )

PCI VPD Card Name field descriptor.

Definition at line 83 of file pcivpd.h.

◆ PCI_VPD_FIELD_PN

#define PCI_VPD_FIELD_PN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'N' )

PCI VPD Part Number field descriptor.

Definition at line 86 of file pcivpd.h.

◆ PCI_VPD_FIELD_EC

#define PCI_VPD_FIELD_EC   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'E', 'C' )

PCI VPD Engineering Change Level field descriptor.

Definition at line 89 of file pcivpd.h.

◆ PCI_VPD_FIELD_FG

#define PCI_VPD_FIELD_FG   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'F', 'G' )

PCI VPD Fabric Geography field descriptor.

Definition at line 92 of file pcivpd.h.

◆ PCI_VPD_FIELD_LC

#define PCI_VPD_FIELD_LC   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'L', 'C' )

PCI VPD Location field descriptor.

Definition at line 95 of file pcivpd.h.

◆ PCI_VPD_FIELD_MN

#define PCI_VPD_FIELD_MN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'M', 'N' )

PCI VPD Manufacturer ID field descriptor.

Definition at line 98 of file pcivpd.h.

◆ PCI_VPD_FIELD_PG

#define PCI_VPD_FIELD_PG   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'G' )

PCI VPD PCI Geography field descriptor.

Definition at line 101 of file pcivpd.h.

◆ PCI_VPD_FIELD_SN

#define PCI_VPD_FIELD_SN   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'S', 'N' )

PCI VPD Serial Number field descriptor.

Definition at line 104 of file pcivpd.h.

◆ PCI_VPD_FIELD_CP

#define PCI_VPD_FIELD_CP   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'C', 'P' )

PCI VPD Extended Capability field descriptor.

Definition at line 107 of file pcivpd.h.

◆ PCI_VPD_FIELD_RV

#define PCI_VPD_FIELD_RV   PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'R', 'V' )

PCI VPD Checksum and Reserved field descriptor.

Definition at line 110 of file pcivpd.h.

◆ PCI_VPD_FIELD_YA

#define PCI_VPD_FIELD_YA   PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'Y', 'A' )

PCI VPD Asset Tag field descriptor.

Definition at line 113 of file pcivpd.h.

◆ PCI_VPD_FIELD_RW

#define PCI_VPD_FIELD_RW   PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'R', 'W' )

PCI VPD Remaining Read/Write Area field descriptor.

Definition at line 116 of file pcivpd.h.

◆ PCI_VPD_MAX_WAIT_MS

#define PCI_VPD_MAX_WAIT_MS   100

Maximum wait for PCI VPD (in ms)

Definition at line 119 of file pcivpd.h.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ pci_vpd_is_present()

static int pci_vpd_is_present ( struct pci_vpd vpd)
inlinestatic

Check for presence of PCI VPD.

Parameters
vpdPCI VPD
Return values
is_presentVPD is present

Definition at line 146 of file pcivpd.h.

146  {
147  return ( vpd->cap != 0 );
148 }
int cap
VPD capability offset.
Definition: pcivpd.h:134

References pci_vpd::cap.

◆ pci_vpd_cache_is_valid()

static int pci_vpd_cache_is_valid ( struct pci_vpd vpd)
inlinestatic

Check if PCI VPD read cache is valid.

Parameters
vpdPCI VPD
Return values
is_validRead cache is valid

Definition at line 157 of file pcivpd.h.

157  {
158  return ( vpd->cache.address >= 0 );
159 }
int address
Address.
Definition: pcivpd.h:124
struct pci_vpd_cache cache
Read cache.
Definition: pcivpd.h:136

References pci_vpd_cache::address, and pci_vpd::cache.

Referenced by pci_vpd_read_dword().

◆ pci_vpd_invalidate_cache()

static void pci_vpd_invalidate_cache ( struct pci_vpd vpd)
inlinestatic

Invalidate PCI VPD read cache.

Parameters
vpdPCI VPD

Definition at line 167 of file pcivpd.h.

167  {
168  vpd->cache.address = -1;
169 }
int address
Address.
Definition: pcivpd.h:124
struct pci_vpd_cache cache
Read cache.
Definition: pcivpd.h:136

References pci_vpd_cache::address, and pci_vpd::cache.

Referenced by pci_vpd_init(), and pci_vpd_write_dword().

◆ pci_vpd_init()

int pci_vpd_init ( struct pci_vpd vpd,
struct pci_device pci 
)

Initialise PCI Vital Product Data.

Parameters
vpdPCI VPD
pciPCI device
Return values
rcReturn status code

Definition at line 48 of file pcivpd.c.

48  {
49 
50  /* Initialise structure */
51  vpd->pci = pci;
53 
54  /* Locate VPD capability */
55  vpd->cap = pci_find_capability ( pci, PCI_CAP_ID_VPD );
56  if ( ! vpd->cap ) {
57  DBGC ( vpd, PCI_FMT " does not support VPD\n",
58  PCI_ARGS ( pci ) );
59  return -ENOTTY;
60  }
61 
62  DBGC ( vpd, PCI_FMT " VPD is at offset %02x\n",
63  PCI_ARGS ( pci ), vpd->cap );
64  return 0;
65 }
int pci_find_capability(struct pci_device *pci, int cap)
Look for a PCI capability.
Definition: pciextra.c:36
#define DBGC(...)
Definition: compiler.h:505
static void pci_vpd_invalidate_cache(struct pci_vpd *vpd)
Invalidate PCI VPD read cache.
Definition: pcivpd.h:167
int cap
VPD capability offset.
Definition: pcivpd.h:134
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:287
struct pci_device * pci
PCI device.
Definition: pcivpd.h:132
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:290
#define PCI_CAP_ID_VPD
Vital product data.
Definition: pci.h:94

References pci_vpd::cap, DBGC, ENOTTY, pci_vpd::pci, PCI_ARGS, PCI_CAP_ID_VPD, pci_find_capability(), PCI_FMT, and pci_vpd_invalidate_cache().

Referenced by nvs_vpd_init().

◆ pci_vpd_read()

int pci_vpd_read ( struct pci_vpd vpd,
unsigned int  address,
void *  buf,
size_t  len 
)

Read PCI VPD.

Parameters
vpdPCI VPD
addressStarting address
bufData buffer
lenLength of data buffer
Return values
rcReturn status code

Definition at line 183 of file pcivpd.c.

184  {
185  uint8_t *bytes = buf;
186  uint32_t data;
187  size_t skip_len;
188  unsigned int i;
189  int rc;
190 
191  /* Calculate length to skip at start of data */
192  skip_len = ( address & 0x03 );
193 
194  /* Read data, a dword at a time */
195  for ( address &= ~0x03 ; len ; address += 4 ) {
196 
197  /* Read whole dword */
198  if ( ( rc = pci_vpd_read_dword ( vpd, address, &data ) ) != 0 )
199  return rc;
200 
201  /* Copy data to buffer */
202  for ( i = 4 ; i ; i-- ) {
203  if ( skip_len ) {
204  skip_len--;
205  } else if ( len ) {
206  *(bytes++) = data;
207  len--;
208  }
209  data = ( ( data << 24 ) | ( data >> 8 ) );
210  }
211  }
212 
213  return 0;
214 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint64_t address
Base address.
Definition: ena.h:24
static int pci_vpd_read_dword(struct pci_vpd *vpd, int address, uint32_t *data)
Read one dword of PCI Vital Product Data.
Definition: pcivpd.c:75
unsigned char uint8_t
Definition: stdint.h:10
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint8_t bytes[64]
Definition: ib_mad.h:16

References address, bytes, data, len, pci_vpd_read_dword(), and rc.

Referenced by nvs_vpd_read(), pci_vpd_dump(), pci_vpd_find(), pci_vpd_find_tag(), and pci_vpd_resize().

◆ pci_vpd_write()

int pci_vpd_write ( struct pci_vpd vpd,
unsigned int  address,
const void *  buf,
size_t  len 
)

Write PCI VPD.

Parameters
vpdPCI VPD
addressStarting address
bufData buffer
lenLength of data buffer
Return values
rcReturn status code

Definition at line 225 of file pcivpd.c.

226  {
227  const uint8_t *bytes = buf;
228  uint32_t data;
229  size_t skip_len;
230  unsigned int i;
231  int rc;
232 
233  /* Calculate length to skip at start of data */
234  skip_len = ( address & 0x03 );
235 
236  /* Write data, a dword at a time */
237  for ( address &= ~0x03 ; len ; address += 4 ) {
238 
239  /* Read existing dword, if necessary */
240  if ( skip_len || ( len <= 0x03 ) ) {
241  if ( ( rc = pci_vpd_read_dword ( vpd, address,
242  &data ) ) != 0 )
243  return rc;
244  }
245 
246  /* Copy data from buffer */
247  for ( i = 4 ; i ; i-- ) {
248  if ( skip_len ) {
249  skip_len--;
250  } else if ( len ) {
251  data = ( ( data & ~0xff ) | *(bytes++) );
252  len--;
253  }
254  data = ( ( data << 24 ) | ( data >> 8 ) );
255  }
256 
257  /* Write whole dword */
258  if ( ( rc = pci_vpd_write_dword ( vpd, address, data ) ) != 0 )
259  return rc;
260  }
261  return 0;
262 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint64_t address
Base address.
Definition: ena.h:24
static int pci_vpd_read_dword(struct pci_vpd *vpd, int address, uint32_t *data)
Read one dword of PCI Vital Product Data.
Definition: pcivpd.c:75
unsigned char uint8_t
Definition: stdint.h:10
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
static int pci_vpd_write_dword(struct pci_vpd *vpd, int address, uint32_t data)
Write one dword of PCI Vital Product Data.
Definition: pcivpd.c:133
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
uint8_t bytes[64]
Definition: ib_mad.h:16

References address, bytes, data, len, pci_vpd_read_dword(), pci_vpd_write_dword(), and rc.

Referenced by nvs_vpd_write(), and pci_vpd_resize().

◆ pci_vpd_find()

int pci_vpd_find ( struct pci_vpd vpd,
unsigned int  field,
unsigned int *  address,
size_t len 
)

Locate PCI VPD field.

Parameters
vpdPCI VPD
fieldVPD field descriptor
Return values
addressAddress of field body
lenLength of field body
rcReturn status code

Definition at line 353 of file pcivpd.c.

354  {
355  struct pci_vpd_field read_field;
356  int rc;
357 
358  /* Locate containing tag */
359  if ( ( rc = pci_vpd_find_tag ( vpd, PCI_VPD_TAG ( field ),
360  address, len ) ) != 0 )
361  return rc;
362 
363  /* Return immediately if we are searching for a whole-tag field */
364  if ( ! PCI_VPD_KEYWORD ( field ) ) {
365  pci_vpd_dump ( vpd, *address, *len );
366  return 0;
367  }
368 
369  /* Scan through fields looking for a match */
370  while ( *len >= sizeof ( read_field ) ) {
371 
372  /* Read field header */
373  if ( ( rc = pci_vpd_read ( vpd, *address, &read_field,
374  sizeof ( read_field ) ) ) != 0 )
375  return rc;
376  *address += sizeof ( read_field );
377  *len -= sizeof ( read_field );
378 
379  /* Check for keyword match */
380  if ( read_field.keyword == PCI_VPD_KEYWORD ( field ) ) {
381  *len = read_field.len;
382  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
383  " is at [%04x,%04zx)\n", PCI_ARGS ( vpd->pci ),
384  PCI_VPD_FIELD_ARGS ( field ),
385  *address, ( *address + *len ) );
386  pci_vpd_dump ( vpd, *address, *len );
387  return 0;
388  }
389 
390  /* Move to next field */
391  if ( read_field.len > *len )
392  break;
393  *address += read_field.len;
394  *len -= read_field.len;
395  }
396 
397  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " not found\n",
398  PCI_ARGS ( vpd->pci ), PCI_VPD_FIELD_ARGS ( field ) );
399  return -ENOENT;
400 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define PCI_VPD_TAG(field)
Extract PCI VPD ISAPnP tag.
Definition: pcivpd.h:60
int pci_vpd_read(struct pci_vpd *vpd, unsigned int address, void *buf, size_t len)
Read PCI VPD.
Definition: pcivpd.c:183
uint64_t address
Base address.
Definition: ena.h:24
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
A PCI VPD field.
Definition: pcivpd.h:28
static int pci_vpd_find_tag(struct pci_vpd *vpd, unsigned int tag, unsigned int *address, size_t *len)
Locate PCI VPD tag.
Definition: pcivpd.c:298
#define PCI_VPD_FIELD_FMT
PCI VPD field debug message format.
Definition: pcivpd.h:70
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:287
#define PCI_VPD_FIELD_ARGS(field)
PCI VPD field debug message arguments.
Definition: pcivpd.h:73
uint32_t len
Length.
Definition: ena.h:14
struct pci_device * pci
PCI device.
Definition: pcivpd.h:132
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:290
static void pci_vpd_dump(struct pci_vpd *vpd, unsigned int address, size_t len)
Dump PCI VPD region (for debugging)
Definition: pcivpd.c:271
#define PCI_VPD_KEYWORD(field)
Extract PCI VPD keyword.
Definition: pcivpd.h:67

References address, DBGC, ENOENT, pci_vpd_field::keyword, len, pci_vpd_field::len, pci_vpd::pci, PCI_ARGS, PCI_FMT, pci_vpd_dump(), PCI_VPD_FIELD_ARGS, PCI_VPD_FIELD_FMT, pci_vpd_find_tag(), PCI_VPD_KEYWORD, pci_vpd_read(), PCI_VPD_TAG, and rc.

Referenced by nvs_vpd_nvo_init(), nvs_vpd_read(), nvs_vpd_write(), and pci_vpd_resize().

◆ pci_vpd_resize()

int pci_vpd_resize ( struct pci_vpd vpd,
unsigned int  field,
size_t  len,
unsigned int *  address 
)

Resize VPD field.

Parameters
vpdPCI VPD
fieldVPD field descriptor
lenNew length of field body
Return values
addressAddress of field body
rcReturn status code

Definition at line 411 of file pcivpd.c.

412  {
413  struct pci_vpd_field rw_field;
414  struct pci_vpd_field old_field;
415  struct pci_vpd_field new_field;
416  unsigned int rw_address;
417  unsigned int old_address;
418  unsigned int copy_address;
419  unsigned int dst_address;
420  unsigned int dump_address;
421  size_t rw_len;
422  size_t old_len;
423  size_t available_len;
424  size_t copy_len;
425  size_t dump_len;
426  void *copy;
427  int rc;
428 
429  /* Sanity checks */
430  assert ( PCI_VPD_TAG ( field ) == PCI_VPD_TAG_RW );
431  assert ( PCI_VPD_KEYWORD ( field ) != 0 );
432  assert ( field != PCI_VPD_FIELD_RW );
433 
434  /* Locate 'RW' field */
435  if ( ( rc = pci_vpd_find ( vpd, PCI_VPD_FIELD_RW, &rw_address,
436  &rw_len ) ) != 0 )
437  goto err_no_rw;
438 
439  /* Locate old field, if any */
440  if ( ( rc = pci_vpd_find ( vpd, field, &old_address,
441  &old_len ) ) == 0 ) {
442 
443  /* Field already exists */
444  if ( old_address > rw_address ) {
445  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
446  " at [%04x,%04zx) is after field "
447  PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
448  PCI_ARGS ( vpd->pci ),
449  PCI_VPD_FIELD_ARGS ( field ),
450  old_address, ( old_address + old_len ),
452  rw_address, ( rw_address + rw_len ) );
453  rc = -ENXIO;
454  goto err_after_rw;
455  }
456  dst_address = ( old_address - sizeof ( old_field ) );
457  copy_address = ( old_address + old_len );
458  copy_len = ( rw_address - sizeof ( rw_field ) - copy_address );
459 
460  /* Calculate available length */
461  available_len = ( rw_len + old_len );
462 
463  } else {
464 
465  /* Field does not yet exist */
466  dst_address = ( rw_address - sizeof ( rw_field ) );
467  copy_address = dst_address;
468  copy_len = 0;
469 
470  /* Calculate available length */
471  available_len = ( ( rw_len > sizeof ( new_field ) ) ?
472  ( rw_len - sizeof ( new_field ) ) : 0 );
473  }
474 
475  /* Dump region before changes */
476  dump_address = dst_address;
477  dump_len = ( rw_address + rw_len - dump_address );
478  DBGC ( vpd, PCI_FMT " VPD before resizing field " PCI_VPD_FIELD_FMT
479  " to %zd bytes:\n", PCI_ARGS ( vpd->pci ),
480  PCI_VPD_FIELD_ARGS ( field ), len );
481  pci_vpd_dump ( vpd, dump_address, dump_len );
482 
483  /* Check available length */
484  if ( available_len > PCI_VPD_MAX_LEN )
485  available_len = PCI_VPD_MAX_LEN;
486  if ( len > available_len ) {
487  DBGC ( vpd, PCI_FMT " VPD no space for field "
488  PCI_VPD_FIELD_FMT " (need %02zx, have %02zx)\n",
489  PCI_ARGS ( vpd->pci ), PCI_VPD_FIELD_ARGS ( field ),
490  len, available_len );
491  rc = -ENOSPC;
492  goto err_no_space;
493  }
494 
495  /* Preserve intermediate fields, if any */
496  copy = malloc ( copy_len );
497  if ( ! copy ) {
498  rc = -ENOMEM;
499  goto err_copy_alloc;
500  }
501  if ( ( rc = pci_vpd_read ( vpd, copy_address, copy, copy_len ) ) != 0 )
502  goto err_copy_read;
503 
504  /* Create new field, if applicable */
505  if ( len ) {
506  new_field.keyword = PCI_VPD_KEYWORD ( field );
507  new_field.len = len;
508  if ( ( rc = pci_vpd_write ( vpd, dst_address, &new_field,
509  sizeof ( new_field ) ) ) != 0 )
510  goto err_new_write;
511  dst_address += sizeof ( new_field );
512  *address = dst_address;
513  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " is now "
514  "at [%04x,%04x)\n", PCI_ARGS ( vpd->pci ),
515  PCI_VPD_FIELD_ARGS ( field ), dst_address,
516  ( dst_address + new_field.len ) );
517  dst_address += len;
518  } else {
519  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT
520  " no longer exists\n", PCI_ARGS ( vpd->pci ),
521  PCI_VPD_FIELD_ARGS ( field ) );
522  }
523 
524  /* Restore intermediate fields, if any */
525  if ( ( rc = pci_vpd_write ( vpd, dst_address, copy, copy_len ) ) != 0 )
526  goto err_copy_write;
527  dst_address += copy_len;
528 
529  /* Create 'RW' field */
530  rw_field.keyword = PCI_VPD_KEYWORD ( PCI_VPD_FIELD_RW );
531  rw_field.len = ( rw_len +
532  ( rw_address - sizeof ( rw_field ) ) - dst_address );
533  if ( ( rc = pci_vpd_write ( vpd, dst_address, &rw_field,
534  sizeof ( rw_field ) ) ) != 0 )
535  goto err_rw_write;
536  dst_address += sizeof ( rw_field );
537  DBGC ( vpd, PCI_FMT " VPD field " PCI_VPD_FIELD_FMT " is now "
538  "at [%04x,%04x)\n", PCI_ARGS ( vpd->pci ),
539  PCI_VPD_FIELD_ARGS ( PCI_VPD_FIELD_RW ), dst_address,
540  ( dst_address + rw_field.len ) );
541 
542  /* Dump region after changes */
543  DBGC ( vpd, PCI_FMT " VPD after resizing field " PCI_VPD_FIELD_FMT
544  " to %zd bytes:\n", PCI_ARGS ( vpd->pci ),
545  PCI_VPD_FIELD_ARGS ( field ), len );
546  pci_vpd_dump ( vpd, dump_address, dump_len );
547 
548  rc = 0;
549 
550  err_rw_write:
551  err_new_write:
552  err_copy_write:
553  err_copy_read:
554  free ( copy );
555  err_copy_alloc:
556  err_no_space:
557  err_after_rw:
558  err_no_rw:
559  return rc;
560 }
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
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define PCI_VPD_TAG(field)
Extract PCI VPD ISAPnP tag.
Definition: pcivpd.h:60
int pci_vpd_read(struct pci_vpd *vpd, unsigned int address, void *buf, size_t len)
Read PCI VPD.
Definition: pcivpd.c:183
uint64_t address
Base address.
Definition: ena.h:24
#define DBGC(...)
Definition: compiler.h:505
A PCI VPD field.
Definition: pcivpd.h:28
#define PCI_VPD_TAG_RW
PCI VPD Read-Write field tag.
Definition: pcivpd.h:80
#define PCI_VPD_MAX_LEN
Maximum PCI VPD field length.
Definition: pcivpd.h:36
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define PCI_VPD_FIELD_FMT
PCI VPD field debug message format.
Definition: pcivpd.h:70
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:287
int pci_vpd_write(struct pci_vpd *vpd, unsigned int address, const void *buf, size_t len)
Write PCI VPD.
Definition: pcivpd.c:225
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
#define PCI_VPD_FIELD_ARGS(field)
PCI VPD field debug message arguments.
Definition: pcivpd.h:73
#define ENXIO
No such device or address.
Definition: errno.h:599
#define ENOSPC
No space left on device.
Definition: errno.h:549
uint32_t len
Length.
Definition: ena.h:14
struct pci_device * pci
PCI device.
Definition: pcivpd.h:132
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:290
static void pci_vpd_dump(struct pci_vpd *vpd, unsigned int address, size_t len)
Dump PCI VPD region (for debugging)
Definition: pcivpd.c:271
#define PCI_VPD_KEYWORD(field)
Extract PCI VPD keyword.
Definition: pcivpd.h:67
#define PCI_VPD_FIELD_RW
PCI VPD Remaining Read/Write Area field descriptor.
Definition: pcivpd.h:116

References address, assert(), DBGC, ENOMEM, ENOSPC, ENXIO, free, pci_vpd_field::keyword, len, pci_vpd_field::len, malloc(), pci_vpd::pci, PCI_ARGS, PCI_FMT, pci_vpd_dump(), PCI_VPD_FIELD_ARGS, PCI_VPD_FIELD_FMT, PCI_VPD_FIELD_RW, pci_vpd_find(), PCI_VPD_KEYWORD, PCI_VPD_MAX_LEN, pci_vpd_read(), PCI_VPD_TAG, PCI_VPD_TAG_RW, pci_vpd_write(), and rc.

Referenced by nvs_vpd_resize().