summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vendorcode/google/chromeos/acpi/vpd.asl226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/vendorcode/google/chromeos/acpi/vpd.asl b/src/vendorcode/google/chromeos/acpi/vpd.asl
new file mode 100644
index 0000000000..3b262f75a8
--- /dev/null
+++ b/src/vendorcode/google/chromeos/acpi/vpd.asl
@@ -0,0 +1,226 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2019 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * This device provides an ACPI interface to read VPD keys from either
+ * the RO_VPD or RW_VPD region. For example:
+ *
+ * VPD.VPDF ("RO", "ro_key_name")
+ * VPD.VPDF ("RW", "rw_key_name")
+ */
+
+Device (VPD)
+{
+ Name (_HID, "GOOG000F")
+ Name (_UID, 1)
+ Name (_STA, 0xf)
+
+ Name (VOFS, 0x600) /* Start of VPD header in VPD region */
+ Name (VIHL, 0x10) /* Length of VPD info header */
+ Name (VPET, 0x00) /* VPD Entry Type: Terminator */
+ Name (VPES, 0x01) /* VPD Entry Type: String */
+ Name (VPEI, 0xfe) /* VPD Entry Type: Info (header) */
+ Name (MORE, 0x80) /* Bit to indicate more length bytes */
+
+ Name (VPTR, Zero) /* Pointer to current byte in VPD for parser */
+ Name (VEND, Zero) /* End of VPD region */
+
+ /*
+ * VLOC() - Return location and length of VPD region in memory.
+ * These values must be initialized in GNVS by coreboot.
+ *
+ * Returns: Package indicating start and length of region:
+ * [0] = Address of the start of VPD region.
+ * [1] = Length of the VPD region.
+ */
+ Method (VLOC, 1, Serialized)
+ {
+ Switch (ToString (Arg0))
+ {
+ Case ("RO") {
+ Return (Package () { \ROVP, \ROVL })
+ }
+ Case ("RW") {
+ Return (Package () { \RWVP, \RWVL })
+ }
+ Default {
+ Return (Package () { Zero, Zero })
+ }
+ }
+ }
+
+ /*
+ * VVPD() - Verify VPD info header.
+ * Arg0: VPD partition base address.
+ * Returns: VPD length or Zero if VPD header is not valid.
+ */
+ Method (VVPD, 1, Serialized)
+ {
+ Local0 = Arg0 + ^VOFS
+
+ OperationRegion (VPDH, SystemMemory, Local0, ^VIHL)
+ Field (VPDH, DWordAcc, NoLock, Preserve)
+ {
+ TYPE, 8, /* VPD Header Tag (=0xfe) */
+ KLEN, 8, /* Key length (=9) */
+ IVER, 8, /* Info version (=1) */
+ SIGN, 64, /* Signature (="gVpdInfo") */
+ VLEN, 8, /* Value length (=4) */
+ SIZE, 32, /* VPD length */
+ }
+
+ If (TYPE != ^VPEI) {
+ Return (Zero)
+ }
+ If (KLEN != 9) {
+ Return (Zero)
+ }
+ If (IVER != 1) {
+ Return (Zero)
+ }
+ If (ToString (SIGN) != "gVpdInfo") {
+ Return (Zero)
+ }
+ If (VLEN != 4) {
+ Return (Zero)
+ }
+
+ Return (SIZE)
+ }
+
+ /* Return next byte from VPD at pointer VPTR, and increment VPTR. */
+ Method (VPRB, 0, Serialized)
+ {
+ If (^VPTR > ^VEND) {
+ Printf ("Access beyond end of VPD region")
+ Return (Zero)
+ }
+
+ Local0 = ^VPTR
+ OperationRegion (VPDR, SystemMemory, Local0, One)
+ Field (VPDR, DWordAcc, NoLock, Preserve)
+ {
+ BYTE, 8,
+ }
+
+ /* Increment address pointer */
+ ^VPTR++
+ Return (BYTE)
+ }
+
+ /* Extract and return next string from VPD. */
+ Method (VPDE, 0, Serialized)
+ {
+ Local0 = One /* Indicates if there are more bytes */
+ Local1 = Zero /* Length */
+
+ /* Decode the string length */
+ While (Local0) {
+ /* Read the next byte at indicated address */
+ Local2 = ^VPRB ()
+
+ /* Update the more bit from the byte in Local2 */
+ Local0 = Local2 >> 7
+
+ /* Save the length bits from Local2 */
+ Local1 <<= 7
+ Local1 |= Local2 & 0x7f
+ }
+ If (!Local1) {
+ Return (Zero)
+ }
+
+ /* Extract the string */
+ Local3 = Zero
+ Local4 = ""
+ While (Local3 < Local1) {
+ Concatenate (Local4, ToString (^VPRB ()), Local4)
+ Local3++
+ }
+
+ Return (Local4)
+ }
+
+ /*
+ * VPDS() - Find next VPD key and value.
+ * Returns: Package containing key and value:
+ * [0] = VPD key string
+ * [1] = VPD value string
+ */
+ Method (VPDS, 0, Serialized)
+ {
+ Name (VPKV, Package () { Zero, Zero })
+
+ /* Read the VPD type and ensure it is a string */
+ If (^VPRB () != ^VPES) {
+ Printf ("VPDS: Type is not a string")
+ Return (VPKV)
+ }
+
+ /* Extract the key string and value */
+ VPKV[0] = VPDE ()
+ VPKV[1] = VPDE ()
+
+ Return (VPKV)
+ }
+
+ /*
+ * VPDF() - Find VPD key with matching name.
+ * Arg0: VPD Partition, either "RO" or "RW".
+ * Arg1: VPD key name to search for.
+ * Returns: VPD string corresponding to VPD key, or Zero if not found.
+ */
+ Method (VPDF, 2, Serialized)
+ {
+ Local0 = VLOC (Arg0)
+
+ /* Start of VPD region */
+ ^VPTR = DerefOf (Local0[0])
+
+ /* End address of VPD region */
+ ^VEND = ^VPTR + DerefOf (Local0[1])
+
+ If (!^VPTR || !^VEND) {
+ Printf ("Unable to find VPD region")
+ Return (Zero)
+ }
+
+ /* Verify VPD info header and save size */
+ Local0 = VVPD (^VPTR)
+ If (!Local0) {
+ Printf ("VPD region %o did not verify", Arg0)
+ Return (Zero)
+ }
+
+ /* Set VPD pointer to start of VPD entries */
+ ^VPTR += ^VOFS + ^VIHL
+
+ /* Search through VPD entries until key is found */
+ Local1 = ""
+ While (Local1 != ToString (Arg1)) {
+ Local2 = VPDS ()
+ Local1 = DerefOf (Local2[0])
+ If (!Local1) {
+ Printf ("VPD KEY %o not found", Arg1)
+ Return (Zero)
+ }
+ }
+ Local3 = DerefOf (Local2[1])
+
+ Printf ("Found VPD KEY %o = %o", Local1, Local3)
+ Return (Local3)
+ }
+}