xref: /openbmc/linux/drivers/pci/vpd.c (revision ddc141e5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * File:	vpd.c
4  * Purpose:	Provide PCI VPD support
5  *
6  * Copyright (C) 2010 Broadcom Corporation.
7  */
8 
9 #include <linux/pci.h>
10 #include <linux/export.h>
11 
12 int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt)
13 {
14 	int i;
15 
16 	for (i = off; i < len; ) {
17 		u8 val = buf[i];
18 
19 		if (val & PCI_VPD_LRDT) {
20 			/* Don't return success of the tag isn't complete */
21 			if (i + PCI_VPD_LRDT_TAG_SIZE > len)
22 				break;
23 
24 			if (val == rdt)
25 				return i;
26 
27 			i += PCI_VPD_LRDT_TAG_SIZE +
28 			     pci_vpd_lrdt_size(&buf[i]);
29 		} else {
30 			u8 tag = val & ~PCI_VPD_SRDT_LEN_MASK;
31 
32 			if (tag == rdt)
33 				return i;
34 
35 			if (tag == PCI_VPD_SRDT_END)
36 				break;
37 
38 			i += PCI_VPD_SRDT_TAG_SIZE +
39 			     pci_vpd_srdt_size(&buf[i]);
40 		}
41 	}
42 
43 	return -ENOENT;
44 }
45 EXPORT_SYMBOL_GPL(pci_vpd_find_tag);
46 
47 int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
48 			      unsigned int len, const char *kw)
49 {
50 	int i;
51 
52 	for (i = off; i + PCI_VPD_INFO_FLD_HDR_SIZE <= off + len;) {
53 		if (buf[i + 0] == kw[0] &&
54 		    buf[i + 1] == kw[1])
55 			return i;
56 
57 		i += PCI_VPD_INFO_FLD_HDR_SIZE +
58 		     pci_vpd_info_field_size(&buf[i]);
59 	}
60 
61 	return -ENOENT;
62 }
63 EXPORT_SYMBOL_GPL(pci_vpd_find_info_keyword);
64