openocd: src/target: replace the GPL-2.0-or-later license tag
[fw/openocd] / src / target / arm_adi_v5.c
index d33dcf85353fec113ec3e59f74c5fc1eed612fb8..ff0d9b5495d6c2691a16eb20b2298eab1513e631 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2006 by Magnus Lundin                                   *
  *   lundin@mlu.mine.nu                                                    *
  *   andreas.fritiofson@gmail.com                                          *
  *                                                                         *
  *   Copyright (C) 2019-2021, Ampere Computing 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; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   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.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 /**
@@ -928,7 +917,9 @@ static const struct {
 };
 
 #define DEVARCH_ID_MASK         (ARM_CS_C9_DEVARCH_ARCHITECT_MASK | ARM_CS_C9_DEVARCH_ARCHID_MASK)
+#define DEVARCH_MEM_AP          ARCH_ID(ARM_ID, 0x0A17)
 #define DEVARCH_ROM_C_0X9       ARCH_ID(ARM_ID, 0x0AF7)
+#define DEVARCH_UNKNOWN_V2      ARCH_ID(ARM_ID, 0x0A47)
 
 static const char *class0x9_devarch_description(uint32_t devarch)
 {
@@ -1180,6 +1171,17 @@ int adiv6_dap_read_baseptr(struct command_invocation *cmd, struct adiv5_dap *dap
        return ERROR_OK;
 }
 
+/**
+ * Method to access the CoreSight component.
+ * On ADIv5, CoreSight components are on the bus behind a MEM-AP.
+ * On ADIv6, CoreSight components can either be on the bus behind a MEM-AP
+ * or directly in the AP.
+ */
+enum coresight_access_mode {
+       CS_ACCESS_AP,
+       CS_ACCESS_MEM_AP,
+};
+
 /** Holds registers and coordinates of a CoreSight component */
 struct cs_component_vals {
        struct adiv5_ap *ap;
@@ -1189,19 +1191,43 @@ struct cs_component_vals {
        uint32_t devarch;
        uint32_t devid;
        uint32_t devtype_memtype;
+       enum coresight_access_mode mode;
 };
 
+/**
+ * Helper to read CoreSight component's registers, either on the bus
+ * behind a MEM-AP or directly in the AP.
+ *
+ * @param mode           Method to access the component (AP or MEM-AP).
+ * @param ap             Pointer to AP containing the component.
+ * @param component_base On MEM-AP access method, base address of the component.
+ * @param reg            Offset of the component's register to read.
+ * @param value          Pointer to the store the read value.
+ *
+ * @return ERROR_OK on success, else a fault code.
+ */
+static int dap_queue_read_reg(enum coresight_access_mode mode, struct adiv5_ap *ap,
+               uint64_t component_base, unsigned int reg, uint32_t *value)
+{
+       if (mode == CS_ACCESS_AP)
+               return dap_queue_ap_read(ap, reg, value);
+
+       /* mode == CS_ACCESS_MEM_AP */
+       return mem_ap_read_u32(ap, component_base + reg, value);
+}
+
 /**
  * Read the CoreSight registers needed during ROM Table Parsing (RTP).
  *
+ * @param mode           Method to access the component (AP or MEM-AP).
  * @param ap             Pointer to AP containing the component.
  * @param component_base On MEM-AP access method, base address of the component.
  * @param v              Pointer to the struct holding the value of registers.
  *
  * @return ERROR_OK on success, else a fault code.
  */
-static int rtp_read_cs_regs(struct adiv5_ap *ap, target_addr_t component_base,
-               struct cs_component_vals *v)
+static int rtp_read_cs_regs(enum coresight_access_mode mode, struct adiv5_ap *ap,
+               target_addr_t component_base, struct cs_component_vals *v)
 {
        assert(IS_ALIGNED(component_base, ARM_CS_ALIGN));
        assert(ap && v);
@@ -1212,6 +1238,7 @@ static int rtp_read_cs_regs(struct adiv5_ap *ap, target_addr_t component_base,
 
        v->ap = ap;
        v->component_base = component_base;
+       v->mode = mode;
 
        /* sort by offset to gain speed */
 
@@ -1221,35 +1248,35 @@ static int rtp_read_cs_regs(struct adiv5_ap *ap, target_addr_t component_base,
         * without triggering error. Read them for eventual use on Class 0x9.
         */
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_C9_DEVARCH, &v->devarch);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_C9_DEVARCH, &v->devarch);
 
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_C9_DEVID, &v->devid);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_C9_DEVID, &v->devid);
 
        /* Same address as ARM_CS_C1_MEMTYPE */
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_C9_DEVTYPE, &v->devtype_memtype);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_C9_DEVTYPE, &v->devtype_memtype);
 
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR4, &pid4);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_PIDR4, &pid4);
 
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR0, &pid0);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_PIDR0, &pid0);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR1, &pid1);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_PIDR1, &pid1);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR2, &pid2);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_PIDR2, &pid2);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_PIDR3, &pid3);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_PIDR3, &pid3);
 
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR0, &cid0);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_CIDR0, &cid0);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR1, &cid1);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_CIDR1, &cid1);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR2, &cid2);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_CIDR2, &cid2);
        if (retval == ERROR_OK)
-               retval = mem_ap_read_u32(ap, component_base + ARM_CS_CIDR3, &cid3);
+               retval = dap_queue_read_reg(mode, ap, component_base, ARM_CS_CIDR3, &cid3);
 
        if (retval == ERROR_OK)
                retval = dap_run(ap->dap);
@@ -1572,17 +1599,26 @@ static int dap_devtype_display(struct command_invocation *cmd, uint32_t devtype)
  * Actions/operations to be executed while parsing ROM tables.
  */
 struct rtp_ops {
+       /**
+        * Executed at the start of a new AP, typically to print the AP header.
+        * @param ap        Pointer to AP.
+        * @param depth     The current depth level of ROM table.
+        * @param priv      Pointer to private data.
+        * @return          ERROR_OK on success, else a fault code.
+        */
+       int (*ap_header)(struct adiv5_ap *ap, int depth, void *priv);
        /**
         * Executed at the start of a new MEM-AP, typically to print the MEM-AP header.
         * @param retval    Error encountered while reading AP.
         * @param ap        Pointer to AP.
         * @param dbgbase   Value of MEM-AP Debug Base Address register.
         * @param apid      Value of MEM-AP IDR Identification Register.
+        * @param depth     The current depth level of ROM table.
         * @param priv      Pointer to private data.
         * @return          ERROR_OK on success, else a fault code.
         */
        int (*mem_ap_header)(int retval, struct adiv5_ap *ap, uint64_t dbgbase,
-                       uint32_t apid, void *priv);
+                       uint32_t apid, int depth, void *priv);
        /**
         * Executed when a CoreSight component is parsed, typically to print
         * information on the component.
@@ -1611,17 +1647,29 @@ struct rtp_ops {
        void *priv;
 };
 
+/**
+ * Wrapper around struct rtp_ops::ap_header.
+ */
+static int rtp_ops_ap_header(const struct rtp_ops *ops,
+               struct adiv5_ap *ap, int depth)
+{
+       if (ops->ap_header)
+               return ops->ap_header(ap, depth, ops->priv);
+
+       return ERROR_OK;
+}
+
 /**
  * Wrapper around struct rtp_ops::mem_ap_header.
  * Input parameter @a retval is propagated.
  */
 static int rtp_ops_mem_ap_header(const struct rtp_ops *ops,
-               int retval, struct adiv5_ap *ap, uint64_t dbgbase, uint32_t apid)
+               int retval, struct adiv5_ap *ap, uint64_t dbgbase, uint32_t apid, int depth)
 {
        if (!ops->mem_ap_header)
                return retval;
 
-       int retval1 = ops->mem_ap_header(retval, ap, dbgbase, apid, ops->priv);
+       int retval1 = ops->mem_ap_header(retval, ap, dbgbase, apid, depth, ops->priv);
        if (retval != ERROR_OK)
                return retval;
        return retval1;
@@ -1670,13 +1718,18 @@ static int rtp_ops_rom_table_entry(const struct rtp_ops *ops,
  */
 #define CORESIGHT_COMPONENT_FOUND (1)
 
-static int rtp_cs_component(const struct rtp_ops *ops,
-               struct adiv5_ap *ap, target_addr_t dbgbase, int depth);
+static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap, int depth);
+static int rtp_cs_component(enum coresight_access_mode mode, const struct rtp_ops *ops,
+               struct adiv5_ap *ap, target_addr_t dbgbase, bool *is_mem_ap, int depth);
 
-static int rtp_rom_loop(const struct rtp_ops *ops,
+static int rtp_rom_loop(enum coresight_access_mode mode, const struct rtp_ops *ops,
                struct adiv5_ap *ap, target_addr_t base_address, int depth,
                unsigned int width, unsigned int max_entries)
 {
+       /* ADIv6 AP ROM table provide offset from current AP */
+       if (mode == CS_ACCESS_AP)
+               base_address = ap->ap_num;
+
        assert(IS_ALIGNED(base_address, ARM_CS_ALIGN));
 
        unsigned int offset = 0;
@@ -1686,10 +1739,10 @@ static int rtp_rom_loop(const struct rtp_ops *ops,
                target_addr_t component_base;
                unsigned int saved_offset = offset;
 
-               int retval = mem_ap_read_u32(ap, base_address + offset, &romentry_low);
+               int retval = dap_queue_read_reg(mode, ap, base_address, offset, &romentry_low);
                offset += 4;
                if (retval == ERROR_OK && width == 64) {
-                       retval = mem_ap_read_u32(ap, base_address + offset, &romentry_high);
+                       retval = dap_queue_read_reg(mode, ap, base_address, offset, &romentry_high);
                        offset += 4;
                }
                if (retval == ERROR_OK)
@@ -1723,7 +1776,18 @@ static int rtp_rom_loop(const struct rtp_ops *ops,
                        continue;
 
                /* Recurse */
-               retval = rtp_cs_component(ops, ap, component_base, depth + 1);
+               if (mode == CS_ACCESS_AP) {
+                       struct adiv5_ap *next_ap = dap_get_ap(ap->dap, component_base);
+                       if (!next_ap) {
+                               LOG_DEBUG("Wrong AP # 0x%" PRIx64, component_base);
+                               continue;
+                       }
+                       retval = rtp_ap(ops, next_ap, depth + 1);
+                       dap_put_ap(next_ap);
+               } else {
+                       /* mode == CS_ACCESS_MEM_AP */
+                       retval = rtp_cs_component(mode, ops, ap, component_base, NULL, depth + 1);
+               }
                if (retval == CORESIGHT_COMPONENT_FOUND)
                        return CORESIGHT_COMPONENT_FOUND;
                if (retval != ERROR_OK) {
@@ -1736,18 +1800,21 @@ static int rtp_rom_loop(const struct rtp_ops *ops,
        return ERROR_OK;
 }
 
-static int rtp_cs_component(const struct rtp_ops *ops,
-               struct adiv5_ap *ap, target_addr_t base_address, int depth)
+static int rtp_cs_component(enum coresight_access_mode mode, const struct rtp_ops *ops,
+               struct adiv5_ap *ap, target_addr_t base_address, bool *is_mem_ap, int depth)
 {
        struct cs_component_vals v;
        int retval;
 
        assert(IS_ALIGNED(base_address, ARM_CS_ALIGN));
 
+       if (is_mem_ap)
+               *is_mem_ap = false;
+
        if (depth > ROM_TABLE_MAX_DEPTH)
                retval = ERROR_FAIL;
        else
-               retval = rtp_read_cs_regs(ap, base_address, &v);
+               retval = rtp_read_cs_regs(mode, ap, base_address, &v);
 
        retval = rtp_ops_cs_component(ops, retval, &v, depth);
        if (retval == CORESIGHT_COMPONENT_FOUND)
@@ -1761,37 +1828,64 @@ static int rtp_cs_component(const struct rtp_ops *ops,
        const unsigned int class = ARM_CS_CIDR_CLASS(v.cid);
 
        if (class == ARM_CS_CLASS_0X1_ROM_TABLE)
-               return rtp_rom_loop(ops, ap, base_address, depth, 32, 960);
+               return rtp_rom_loop(mode, ops, ap, base_address, depth, 32, 960);
 
        if (class == ARM_CS_CLASS_0X9_CS_COMPONENT) {
                if ((v.devarch & ARM_CS_C9_DEVARCH_PRESENT) == 0)
                        return ERROR_OK;
 
+               if (is_mem_ap) {
+                       if ((v.devarch & DEVARCH_ID_MASK) == DEVARCH_MEM_AP)
+                               *is_mem_ap = true;
+
+                       /* SoC-600 APv1 Adapter */
+                       if ((v.devarch & DEVARCH_ID_MASK) == DEVARCH_UNKNOWN_V2 &&
+                                       ARM_CS_PIDR_DESIGNER(v.pid) == ARM_ID &&
+                                       ARM_CS_PIDR_PART(v.pid) == 0x9e5)
+                               *is_mem_ap = true;
+               }
+
                /* quit if not ROM table */
                if ((v.devarch & DEVARCH_ID_MASK) != DEVARCH_ROM_C_0X9)
                        return ERROR_OK;
 
                if ((v.devid & ARM_CS_C9_DEVID_FORMAT_MASK) == ARM_CS_C9_DEVID_FORMAT_64BIT)
-                       return rtp_rom_loop(ops, ap, base_address, depth, 64, 256);
+                       return rtp_rom_loop(mode, ops, ap, base_address, depth, 64, 256);
                else
-                       return rtp_rom_loop(ops, ap, base_address, depth, 32, 512);
+                       return rtp_rom_loop(mode, ops, ap, base_address, depth, 32, 512);
        }
 
        /* Class other than 0x1 and 0x9 */
        return ERROR_OK;
 }
 
-static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap)
+static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap, int depth)
 {
-       int retval;
        uint32_t apid;
        target_addr_t dbgbase, invalid_entry;
 
+       int retval = rtp_ops_ap_header(ops, ap, depth);
+       if (retval != ERROR_OK || depth > ROM_TABLE_MAX_DEPTH)
+               return ERROR_OK; /* Don't abort recursion */
+
+       if (is_adiv6(ap->dap)) {
+               bool is_mem_ap;
+               retval = rtp_cs_component(CS_ACCESS_AP, ops, ap, 0, &is_mem_ap, depth);
+               if (retval == CORESIGHT_COMPONENT_FOUND)
+                       return CORESIGHT_COMPONENT_FOUND;
+               if (retval != ERROR_OK)
+                       return ERROR_OK; /* Don't abort recursion */
+
+               if (!is_mem_ap)
+                       return ERROR_OK;
+               /* Continue for an ADIv6 MEM-AP or SoC-600 APv1 Adapter */
+       }
+
        /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec  */
        retval = dap_get_debugbase(ap, &dbgbase, &apid);
        if (retval != ERROR_OK)
                return retval;
-       retval = rtp_ops_mem_ap_header(ops, retval, ap, dbgbase, apid);
+       retval = rtp_ops_mem_ap_header(ops, retval, ap, dbgbase, apid, depth);
        if (retval != ERROR_OK)
                return retval;
 
@@ -1810,7 +1904,8 @@ static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap)
                        invalid_entry = 0xFFFFFFFFul;
 
                if (dbgbase != invalid_entry && (dbgbase & 0x3) != 0x2) {
-                       retval = rtp_cs_component(ops, ap, dbgbase & 0xFFFFFFFFFFFFF000ull, 0);
+                       retval = rtp_cs_component(CS_ACCESS_MEM_AP, ops, ap,
+                                       dbgbase & 0xFFFFFFFFFFFFF000ull, NULL, depth);
                        if (retval == CORESIGHT_COMPONENT_FOUND)
                                return CORESIGHT_COMPONENT_FOUND;
                }
@@ -1821,24 +1916,46 @@ static int rtp_ap(const struct rtp_ops *ops, struct adiv5_ap *ap)
 
 /* Actions for command "dap info" */
 
+static int dap_info_ap_header(struct adiv5_ap *ap, int depth, void *priv)
+{
+       struct command_invocation *cmd = priv;
+
+       if (depth > ROM_TABLE_MAX_DEPTH) {
+               command_print(cmd, "\tTables too deep");
+               return ERROR_FAIL;
+       }
+
+       command_print(cmd, "%sAP # 0x%" PRIx64, (depth) ? "\t\t" : "", ap->ap_num);
+       return ERROR_OK;
+}
+
 static int dap_info_mem_ap_header(int retval, struct adiv5_ap *ap,
-               target_addr_t dbgbase, uint32_t apid, void *priv)
+               target_addr_t dbgbase, uint32_t apid, int depth, void *priv)
 {
        struct command_invocation *cmd = priv;
        target_addr_t invalid_entry;
+       char tabs[17] = "";
 
        if (retval != ERROR_OK) {
                command_print(cmd, "\t\tCan't read MEM-AP, the corresponding core might be turned off");
                return retval;
        }
 
-       command_print(cmd, "AP ID register 0x%8.8" PRIx32, apid);
+       if (depth > ROM_TABLE_MAX_DEPTH) {
+               command_print(cmd, "\tTables too deep");
+               return ERROR_FAIL;
+       }
+
+       if (depth)
+               snprintf(tabs, sizeof(tabs), "\t[L%02d] ", depth);
+
+       command_print(cmd, "\t\tAP ID register 0x%8.8" PRIx32, apid);
        if (apid == 0) {
-               command_print(cmd, "No AP found at this AP#0x%" PRIx64, ap->ap_num);
+               command_print(cmd, "\t\tNo AP found at this AP#0x%" PRIx64, ap->ap_num);
                return ERROR_FAIL;
        }
 
-       command_print(cmd, "\tType is %s", ap_type_to_description(apid & AP_TYPE_MASK));
+       command_print(cmd, "\t\tType is %s", ap_type_to_description(apid & AP_TYPE_MASK));
 
        /* NOTE: a MEM-AP may have a single CoreSight component that's
         * not a ROM table ... or have no such components at all.
@@ -1851,15 +1968,15 @@ static int dap_info_mem_ap_header(int retval, struct adiv5_ap *ap,
                else
                        invalid_entry = 0xFFFFFFFFul;
 
-               command_print(cmd, "MEM-AP BASE " TARGET_ADDR_FMT, dbgbase);
+               command_print(cmd, "%sMEM-AP BASE " TARGET_ADDR_FMT, tabs, dbgbase);
 
                if (dbgbase == invalid_entry || (dbgbase & 0x3) == 0x2) {
-                       command_print(cmd, "\tNo ROM table present");
+                       command_print(cmd, "\t\tNo ROM table present");
                } else {
                        if (dbgbase & 0x01)
-                               command_print(cmd, "\tValid ROM table present");
+                               command_print(cmd, "\t\tValid ROM table present");
                        else
-                               command_print(cmd, "\tROM table in legacy format");
+                               command_print(cmd, "\t\tROM table in legacy format");
                }
        }
 
@@ -1875,7 +1992,8 @@ static int dap_info_cs_component(int retval, struct cs_component_vals *v, int de
                return ERROR_FAIL;
        }
 
-       command_print(cmd, "\t\tComponent base address " TARGET_ADDR_FMT, v->component_base);
+       if (v->mode == CS_ACCESS_MEM_AP)
+               command_print(cmd, "\t\tComponent base address " TARGET_ADDR_FMT, v->component_base);
 
        if (retval != ERROR_OK) {
                command_print(cmd, "\t\tCan't read component, the corresponding core might be turned off");
@@ -1986,13 +2104,14 @@ static int dap_info_rom_table_entry(int retval, int depth,
 int dap_info_command(struct command_invocation *cmd, struct adiv5_ap *ap)
 {
        struct rtp_ops dap_info_ops = {
+               .ap_header       = dap_info_ap_header,
                .mem_ap_header   = dap_info_mem_ap_header,
                .cs_component    = dap_info_cs_component,
                .rom_table_entry = dap_info_rom_table_entry,
                .priv            = cmd,
        };
 
-       return rtp_ap(&dap_info_ops, ap);
+       return rtp_ap(&dap_info_ops, ap, 0);
 }
 
 /* Actions for dap_lookup_cs_component() */
@@ -2003,6 +2122,7 @@ struct dap_lookup_data {
        unsigned int type;
        /* output */
        uint64_t component_base;
+       uint64_t ap_num;
 };
 
 static int dap_lookup_cs_component_cs_component(int retval,
@@ -2031,6 +2151,7 @@ static int dap_lookup_cs_component_cs_component(int retval,
 
        /* Found! */
        lookup->component_base = v->component_base;
+       lookup->ap_num = v->ap->ap_num;
        return CORESIGHT_COMPONENT_FOUND;
 }
 
@@ -2042,14 +2163,20 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, uint8_t type,
                .idx  = core_id,
        };
        struct rtp_ops dap_lookup_cs_component_ops = {
+               .ap_header       = NULL,
                .mem_ap_header   = NULL,
                .cs_component    = dap_lookup_cs_component_cs_component,
                .rom_table_entry = NULL,
                .priv            = &lookup,
        };
 
-       int retval = rtp_ap(&dap_lookup_cs_component_ops, ap);
+       int retval = rtp_ap(&dap_lookup_cs_component_ops, ap, 0);
        if (retval == CORESIGHT_COMPONENT_FOUND) {
+               if (lookup.ap_num != ap->ap_num) {
+                       /* TODO: handle search from root ROM table */
+                       LOG_DEBUG("CS lookup ended in AP # 0x%" PRIx64 ". Ignore it", lookup.ap_num);
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
                LOG_DEBUG("CS lookup found at 0x%" PRIx64, lookup.component_base);
                *addr = lookup.component_base;
                return ERROR_OK;