bmcweb: Implement PartLocationContext for devpath3

Implements https://github.com/DMTF/Redfish/pull/5481

PartLocationContext along with ServiceLabel uniquely identifies part
in an enclosure where just the ServiceLabel cannot.

PartLocationContext is derived from LocationCode following Chassis
associations - Chassis to Chassis using '/contained_by' association and
Chassis to other objects using '/chassis'.

Example:
Upstream chassis assocations for a Processor resource:
cpu0
    <-{/chassis} ChassisC
        <-{/contained_by} ChassisB
            <-{/contained_by} ChassisA

Location object based on the associations above:
    "Location": {
    "PartLocationContext": <ChassisB LocationCode> / <ChassisC LocationCode>
    "PartLocation": {
        "LocationType": "Slot"
        "ServiceLabel": "<cpu0 LocationCode>"
    },

Tested:

wget -qO- localhost/redfish/v1/Chassis/AgoraV2/Assembly
{
  "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly",
  "@odata.type": "#Assembly.v1_3_0.Assembly",
  "Assemblies": [
    {
      "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly#/Assemblies/0",
      "@odata.type": "#Assembly.v1_3_0.AssemblyData",
      "Location": {
        "PartLocation": {
          "LocationType": "Slot",
          "ServiceLabel": "BIOS"
        },
        "PartLocationContext": "DC_SCM"
      },
      "MemberId": "0",
      "Name": "BIOS_flash"
    },
    {
      "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly#/Assemblies/1",
      "@odata.type": "#Assembly.v1_3_0.AssemblyData",
      "Location": {
        "PartLocation": {
          "LocationType": "Slot",
          "ServiceLabel": "BMC"
        },
        "PartLocationContext": "DC_SCM"
      },
      "MemberId": "1",
      "Name": "BMC_flash"
    }
  ],
  "Assemblies@odata.count": 2,
  "Id": "Assembly",
  "Name": "Assembly Collection"
}

Google-Bug-Id: 276470977
Change-Id: I9c4aae49e13c4803435de1bf13683269f8db1192
Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
(cherry picked from commit beef8d560173d9af16abfdc769546ee2007b4587)
diff --git a/recipes-phosphor/interfaces/bmcweb/0001-Add-function-to-get-associated-chassis-subtree.patch b/recipes-phosphor/interfaces/bmcweb/0001-Add-function-to-get-associated-chassis-subtree.patch
new file mode 100644
index 0000000..860a10a
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0001-Add-function-to-get-associated-chassis-subtree.patch
@@ -0,0 +1,96 @@
+From a8f9ef3336341e619dfaf6f86a89291fbc4e8541 Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Mon, 8 May 2023 20:09:46 +0000
+Subject: [PATCH] Add function to get associated chassis subtree
+
+The helper function getAssociatedChassisSubtree is used to get subtree
+that implements chassis specific interfaces and endpoint of given
+association path.
+
+This utiliy is used to get more information on associated chassis where
+just the knowledge of associated endpoint path is not enough.
+For example, if we want to find out LocationCode property of chassis
+associatied with processor, we need to know the service that implements
+the endpoint and chassis interface which this function can help
+identify.
+
+Tested: No changes to redfish tree
+
+Patch Tracking Bug: b/281933570
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62835
+Upstream-Status: Submitted
+Justification: Required for devpath3 to unblock simplicius
+
+Change-Id: I34178d4fe68b80330b35c00abb821aa86628bb32
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/include/utils/chassis_utils.hpp | 40 ++++++++++++++++++--
+ 1 file changed, 36 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/include/utils/chassis_utils.hpp b/redfish-core/include/utils/chassis_utils.hpp
+index 9c7c7db6..6b85134f 100644
+--- a/redfish-core/include/utils/chassis_utils.hpp
++++ b/redfish-core/include/utils/chassis_utils.hpp
+@@ -12,6 +12,11 @@ namespace redfish
+ 
+ namespace chassis_utils
+ {
++
++constexpr std::array<std::string_view, 2> chassisInterfaces = {
++    "xyz.openbmc_project.Inventory.Item.Board",
++    "xyz.openbmc_project.Inventory.Item.Chassis"};
++
+ /**
+  * @brief Retrieves valid chassis path
+  * @param asyncResp   Pointer to object holding response data
+@@ -22,13 +27,10 @@ void getValidChassisPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                          const std::string& chassisId, Callback&& callback)
+ {
+     BMCWEB_LOG_DEBUG << "checkChassisId enter";
+-    constexpr std::array<std::string_view, 2> interfaces = {
+-        "xyz.openbmc_project.Inventory.Item.Board",
+-        "xyz.openbmc_project.Inventory.Item.Chassis"};
+ 
+     // Get the Chassis Collection
+     dbus::utility::getSubTreePaths(
+-        "/xyz/openbmc_project/inventory", 0, interfaces,
++        "/xyz/openbmc_project/inventory", 0, chassisInterfaces,
+         [callback{std::forward<Callback>(callback)}, asyncResp,
+          chassisId](const boost::system::error_code& ec,
+                     const dbus::utility::MapperGetSubTreePathsResponse&
+@@ -63,5 +65,35 @@ void getValidChassisPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+     BMCWEB_LOG_DEBUG << "checkChassisId exit";
+ }
+ 
++/**
++ * @brief Get subtree for associated endpoint with chassis interfaces.
++ * @param asyncResp         Pointer to object holding response data
++ * @param associationPath   Path used to associate with chassis endpoints
++ * @param callback          Callback to process subtree response
++ */
++template <typename Callback>
++inline void getAssociatedChassisSubtree(
++    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++    const std::string& associationPath, Callback&& callback)
++{
++    sdbusplus::message::object_path association(associationPath);
++    sdbusplus::message::object_path root("/xyz/openbmc_project/inventory");
++    dbus::utility::getAssociatedSubTree(
++        association, root, 0, chassisInterfaces,
++        [asyncResp, associationPath,
++         callback{std::forward<Callback>(callback)}](
++            const boost::system::error_code& ec,
++            const dbus::utility::MapperGetSubTreeResponse& subtree) {
++        if (ec)
++        {
++            BMCWEB_LOG_ERROR << "Failed to get chassis associations for "
++                             << associationPath << " ec: " << ec.message();
++            messages::internalError(asyncResp->res);
++            return;
++        }
++        callback(asyncResp, subtree);
++        });
++}
++
+ } // namespace chassis_utils
+ } // namespace redfish
diff --git a/recipes-phosphor/interfaces/bmcweb/0003-location_utils-Implement-PartLocationContext.patch b/recipes-phosphor/interfaces/bmcweb/0003-location_utils-Implement-PartLocationContext.patch
new file mode 100644
index 0000000..d0c4ccf
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0003-location_utils-Implement-PartLocationContext.patch
@@ -0,0 +1,201 @@
+From 2f59d4fdbbf20bb2a2074ad76121319460e834f2 Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Mon, 8 May 2023 07:36:41 +0000
+Subject: [PATCH] location_utils: Implement PartLocationContext
+
+Implements https://github.com/DMTF/Redfish/pull/5481
+PartLocationContext along with ServiceLabel uniquely identifies part
+in an enclosure where just the ServiceLabel cannot.
+
+PartLocationContext is derived from LocationCode following Chassis
+associations - Chassis to Chassis using '/contained_by' association and
+Chassis to other objects using '/chassis'.
+
+Example:
+Upstream chassis assocations for a Processor resource:
+cpu0
+    <-{/chassis} ChassisC
+        <-{/contained_by} ChassisB
+            <-{/contained_by} ChassisA
+
+Location object based on the associations above:
+    "Location": {
+    "PartLocationContext": <ChassisB LocationCode> / <ChassisC LocationCode>
+    "PartLocation": {
+        "LocationType": "Slot"
+        "ServiceLabel": "<cpu0 LocationCode>"
+    },
+
+Patch Tracking Bug: b/281934664
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62834
+Upstream-Status: Submitted
+Justification: Required for devpath3 to unblock simplicius
+
+Change-Id: I3ad685bbe291710845e933534a3278355dd75b9b
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+Signed-off-by: Willy Tu <wltu@google.com>
+---
+ redfish-core/include/utils/location_utils.hpp | 138 ++++++++++++++++++
+ 1 file changed, 138 insertions(+)
+
+diff --git a/redfish-core/include/utils/location_utils.hpp b/redfish-core/include/utils/location_utils.hpp
+index 461634bd..fafafe3b 100644
+--- a/redfish-core/include/utils/location_utils.hpp
++++ b/redfish-core/include/utils/location_utils.hpp
+@@ -1,12 +1,15 @@
+ #pragma once
+ 
++#include "chassis_utils.hpp"
+ #include "dbus_singleton.hpp"
++#include "dbus_utility.hpp"
+ #include "error_messages.hpp"
+ 
+ #include <async_resp.hpp>
+ #include <sdbusplus/asio/property.hpp>
+ 
+ #include <string>
++#include <unordered_set>
+ 
+ namespace redfish
+ {
+@@ -81,5 +84,140 @@ inline void
+         });
+ }
+ 
++/**
++ * @brief Fill out PartLocationContext of a redfish resource.
++ *
++ * @param[in,out]   asyncResp  Async HTTP response
++ * @param[in]       jsonPtr    Json path of where to put the location context
++ * @param[in]       label      Service label to update the location context with
++ */
++inline void
++    updateLocationContext(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++                          const nlohmann::json::json_pointer& jsonPtr,
++                          const std::string& label)
++{
++    BMCWEB_LOG_DEBUG << "Add service label " << label
++                     << " to PartLocationContext";
++    nlohmann::json& propertyJson =
++        asyncResp->res.jsonValue[jsonPtr]["PartLocationContext"];
++    const std::string* val = propertyJson.get_ptr<const std::string*>();
++    if (val != nullptr && !val->empty())
++    {
++        propertyJson = label + "/" + *val;
++    }
++    else
++    {
++        propertyJson = label;
++    }
++}
++
++/**
++ * @brief Parses given chassis subtree for object path and connection to retrive
++ * chassis location code used to fill PartLocationContext.
++ *
++ * @param[in]       upstreamChassisPaths   Set of chassis object paths queried.
++ * @param[in]       jsonPtr     Json location to fill PartLocationContext
++ * @param[in,out]   asyncResp   Async HTTP response
++ * @param[in]       subtree     Subtree associated with chassis endpoint
++ */
++inline void getAssociatedChassisSubtreeCallback(
++    std::unordered_set<std::string> upstreamChassisPaths,
++    const nlohmann::json::json_pointer& jsonPtr,
++    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++    const dbus::utility::MapperGetSubTreeResponse& subtree)
++{
++    // Base case as we recurse to get upstream chassis association.
++    if (subtree.empty())
++    {
++        BMCWEB_LOG_DEBUG << "Chassis association not found."
++                            "Must be root chassis or link is broken";
++        return;
++    }
++
++    if (subtree.size() > 1)
++    {
++        BMCWEB_LOG_ERROR << "Found multiple upstream chassis.";
++        messages::internalError(asyncResp->res);
++        return;
++    }
++
++    auto chassisPathToConnMap = subtree.begin();
++
++    // Upstream chassis.
++    const std::string& chassisPath = chassisPathToConnMap->first;
++    if (!upstreamChassisPaths.emplace(chassisPath).second)
++    {
++        BMCWEB_LOG_ERROR << "Loop detected in upstream chassis associations.";
++        messages::internalError(asyncResp->res);
++        return;
++    }
++
++    const dbus::utility::MapperServiceMap& serviceMap =
++        chassisPathToConnMap->second;
++    if (serviceMap.empty())
++    {
++        BMCWEB_LOG_ERROR << "Associated chassis obj path " << chassisPath
++                         << " has no service mapping.";
++        messages::internalError(asyncResp->res);
++        return;
++    }
++
++    if (serviceMap.size() > 1)
++    {
++        BMCWEB_LOG_ERROR << "Associated chassis path " << chassisPath
++                         << " found in multiple connections";
++        messages::internalError(asyncResp->res);
++        return;
++    }
++
++    // Get service name to retrieve upstream chassis location code property.
++    const std::string& service = serviceMap.begin()->first;
++
++    sdbusplus::asio::getProperty<std::string>(
++        *crow::connections::systemBus, service, chassisPath,
++        "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
++        [asyncResp, jsonPtr, chassisPath,
++         upstreamChassisPaths](const boost::system::error_code ec2,
++                               const std::string& locationCode) {
++        if (ec2)
++        {
++            BMCWEB_LOG_DEBUG << "DBUS response error for Location, ec: "
++                             << ec2.message();
++            return;
++        }
++
++        updateLocationContext(asyncResp, jsonPtr, locationCode);
++
++        chassis_utils::getAssociatedChassisSubtree(
++            asyncResp, chassisPath + "/contained_by",
++            std::bind_front(getAssociatedChassisSubtreeCallback,
++                            upstreamChassisPaths, jsonPtr));
++        });
++}
++
++/**
++ * @brief Recursively gets LocationCode for upstream chassis to populate
++ * PartLocationContext.
++ *
++ * @param[in,out]   asyncResp       Async HTTP response
++ * @param[in]       jsonPtr         Json location to fill PartLocationContext
++ * @param[in]       associationPath Path used to associate with upstream chassis
++ */
++inline void
++    getPartLocationContext(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++                           const nlohmann::json::json_pointer& jsonPtr,
++                           const std::string& associationPath)
++{
++    BMCWEB_LOG_DEBUG << "Get chassis endpoints associated with "
++                     << associationPath;
++    // Set of chassis object paths used to detect cycle as we resolve usptream
++    // chassis associations to get to root chassis to create PartLocationContext
++    std::unordered_set<std::string> upstreamChassisPaths;
++    chassis_utils::getAssociatedChassisSubtree(
++        asyncResp, associationPath,
++        std::bind_front(getAssociatedChassisSubtreeCallback,
++                        std::move(upstreamChassisPaths), jsonPtr));
++}
++
+ } // namespace location_util
+ } // namespace redfish
diff --git a/recipes-phosphor/interfaces/bmcweb/0005-Drive-Add-Reset-Action-for-drive.patch b/recipes-phosphor/interfaces/bmcweb/0005-Drive-Add-Reset-Action-for-drive.patch
index a5fb000..3252f0c 100644
--- a/recipes-phosphor/interfaces/bmcweb/0005-Drive-Add-Reset-Action-for-drive.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0005-Drive-Add-Reset-Action-for-drive.patch
@@ -1,4 +1,4 @@
-From fc83c853b7bccb7863a573e83af82451ce3a8a0d Mon Sep 17 00:00:00 2001
+From 3dd150245201bd1f06edfc6bfbedd7da267adb51 Mon Sep 17 00:00:00 2001
 From: Willy Tu <wltu@google.com>
 Date: Thu, 10 Jun 2021 14:35:51 -0700
 Subject: [PATCH] Drive: Add Reset Action for drive
@@ -112,6 +112,7 @@
   Need to refactor it and plan to submit it by late Q12023.
 Change-Id: Icf4a6c177c94aba31d9072a61d4d9d569e7e67cb
 Signed-off-by: Willy Tu <wltu@google.com>
+
 ---
  redfish-core/include/redfish.hpp |   2 +
  redfish-core/lib/storage.hpp     | 480 ++++++++++++++++++++++++++++---
@@ -131,21 +132,21 @@
          requestRoutesUpdateServiceActionsSimpleUpdate(app);
  #endif
 diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
-index 66710147..c29861c6 100644
+index d87df5f4..f32f797c 100644
 --- a/redfish-core/lib/storage.hpp
 +++ b/redfish-core/lib/storage.hpp
 @@ -32,6 +32,7 @@
-
+ 
  #include <array>
  #include <string_view>
 +#include <unordered_set>
-
+ 
  namespace redfish
  {
 @@ -433,6 +434,19 @@ inline std::optional<std::string> convertDriveType(const std::string& type)
      return std::nullopt;
  }
-
+ 
 +inline void addResetLinks(nlohmann::json& driveReset,
 +                          const std::string& driveId,
 +                          const std::string& chassisId)
@@ -163,7 +164,7 @@
  {
      if (proto == "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.SAS")
 @@ -457,16 +471,18 @@ inline std::optional<std::string> convertDriveProtocol(const std::string& proto)
-
+ 
  inline void
      getDriveItemProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
 +                           const std::string& driveId,
@@ -205,7 +206,7 @@
          }
          });
  }
-
+ 
 -static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
 -                            const std::string& connectionName,
 -                            const std::string& path,
@@ -233,10 +234,10 @@
          {
 -            getDriveItemProperties(asyncResp, connectionName, path);
 +            driveInterface = true;
+             location_util::getPartLocationContext(
+                 asyncResp, "/PhysicalLocation"_json_pointer, path + "/chassis");
          }
-         else if (interface ==
-                  "xyz.openbmc_project.Inventory.Decorator.LocationCode")
-@@ -604,6 +637,12 @@ static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+@@ -606,6 +639,12 @@ static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                  *locationType;
          }
      }
@@ -247,23 +248,23 @@
 +                               path, driveStateInterface);
 +    }
  }
-
+ 
  /**
-@@ -753,8 +792,8 @@ inline void buildDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+@@ -755,8 +794,8 @@ inline void buildDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
              crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId);
          asyncResp->res.jsonValue["Links"]["Chassis"] = linkChassisNav;
-
+ 
 -        addAllDriveInfo(asyncResp, connectionNames[0].first, path,
 -                        connectionNames[0].second);
 +        addAllDriveInfo(asyncResp, driveName, connectionNames[0].first, path,
 +                        connectionNames[0].second, chassisId);
      }
  }
-
-@@ -787,26 +826,22 @@ inline void
+ 
+@@ -789,26 +828,22 @@ inline void
      messages::internalError(asyncResp->res);
  }
-
+ 
 -inline void
 -    handleChassisDriveGet(crow::App& app, const crow::Request& req,
 -                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -295,10 +296,10 @@
          if (ec)
          {
              messages::internalError(asyncResp->res);
-@@ -828,22 +863,34 @@ inline void
+@@ -830,22 +865,34 @@ inline void
                  continue;
              }
-
+ 
 -            dbus::utility::getAssociationEndPoints(
 -                path + "/drive",
 -                [asyncResp, chassisId,
@@ -315,7 +316,7 @@
          }
          });
  }
-
+ 
 +inline void
 +    handleChassisDriveGet(crow::App& app, const crow::Request& req,
 +                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -341,10 +342,10 @@
  /**
   * This URL will show the drive interface for the specific drive in the chassis
   */
-@@ -855,6 +902,369 @@ inline void requestRoutesChassisDriveName(App& app)
+@@ -857,6 +904,369 @@ inline void requestRoutesChassisDriveName(App& app)
              std::bind_front(handleChassisDriveGet, std::ref(app)));
  }
-
+ 
 +inline void setResetType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
 +                         const std::string& driveId, const std::string& action,
 +                         const dbus::utility::MapperGetSubTreeResponse& subtree)
@@ -711,6 +712,3 @@
  inline void getStorageControllerAsset(
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const boost::system::error_code& ec,
---
-2.40.0.634.g4ca3ef3211-goog
-
diff --git a/recipes-phosphor/interfaces/bmcweb/0005-Processor-Add-PartLocationContext-in-Processor.patch b/recipes-phosphor/interfaces/bmcweb/0005-Processor-Add-PartLocationContext-in-Processor.patch
new file mode 100644
index 0000000..6c77c09
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0005-Processor-Add-PartLocationContext-in-Processor.patch
@@ -0,0 +1,50 @@
+From 937afa5d4d1b4886a0ea3f9f93c3fb7b7db4dbcb Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Mon, 8 May 2023 20:56:45 +0000
+Subject: [PATCH] Processor: Add PartLocationContext in Processor
+
+Implements https://github.com/DMTF/Redfish/pull/5481 for Processor
+resource.
+
+Tested:
+Schema not released yet, cannot run Redfish validator. Tested wget
+
+{
+  "@odata.id": "/redfish/v1/Systems/system/Processors/processor0",
+  "@odata.type": "#Processor.v1_11_0.Processor",
+  "Id": "processor0",
+  "Location": {
+    "PartLocation": {
+      "LocationType": "Slot",
+      "ServiceLabel": "PEZ"
+    },
+    "PartLocationContext": "PEX/PEY"
+  },
+  "Name": "processor0",
+  ...
+}
+
+Patch Tracking Bug: b/281934477
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62836
+Upstream-Status: Submitted
+Justification: Required for devpath3 implementation
+
+Change-Id: I784777dedce457dd5d20a2dda3237288e5981785
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/lib/processor.hpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp
+index 607ff7fc..b647de8d 100644
+--- a/redfish-core/lib/processor.hpp
++++ b/redfish-core/lib/processor.hpp
+@@ -754,6 +754,8 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+             {
+                 location_util::getLocationCode(aResp, serviceName, objectPath,
+                                                "/Location"_json_pointer);
++                location_util::getPartLocationContext(
++                    aResp, "/Location"_json_pointer, objectPath + "/chassis");
+             }
+             else if (interface == "xyz.openbmc_project.Common.UUID")
+             {
diff --git a/recipes-phosphor/interfaces/bmcweb/0009-Chassis-Add-PartLocationContext-in-chassis.patch b/recipes-phosphor/interfaces/bmcweb/0009-Chassis-Add-PartLocationContext-in-chassis.patch
new file mode 100644
index 0000000..8f23b77
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0009-Chassis-Add-PartLocationContext-in-chassis.patch
@@ -0,0 +1,95 @@
+From 31cb299f58cec3aeac296ec604ebf03b63eb8ac9 Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Mon, 8 May 2023 21:54:36 +0000
+Subject: [PATCH] Chassis: Add PartLocationContext in chassis
+
+Implements https://github.com/DMTF/Redfish/pull/5481
+
+Tested:
+Redfish validator not run- Schema not released yet. Tested wget
+```
+{
+  "@odata.id": "/redfish/v1/Chassis/chassis2",
+  "@odata.type": "#Chassis.v1_14_0.Chassis",
+  "Actions": {
+    "#Chassis.Reset": {
+      "@Redfish.ActionInfo": "/redfish/v1/Chassis/chassis2/ResetActionInfo",
+      "target": "/redfish/v1/Chassis/chassis2/Actions/Chassis.Reset"
+    }
+  },
+  "ChassisType": "RackMount",
+  "Id": "chassis2",
+  "Links": {
+    "ComputerSystems": [
+      {
+        "@odata.id": "/redfish/v1/Systems/system"
+      }
+    ],
+    "ManagedBy": [
+      {
+        "@odata.id": "/redfish/v1/Managers/bmc"
+      }
+    ],
+  },
+  "Location": {
+    "PartLocation": {
+      "LocationType": "Slot",
+      "ServiceLabel": "PEZ"
+    },
+    "PartLocationContext": "PEX/PEY"
+  },
+...
+}
+
+Patch Tracking Bug: b/281935488
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62838
+Upstream-Status: Submitted
+Justification: Required for devpath3 implementation
+
+Change-Id: I99fdf3a237f0fbee248af8eccdd3bafcfa543ef4
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+
+---
+ redfish-core/lib/chassis.hpp | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
+index 3a270d57..2be6f938 100644
+--- a/redfish-core/lib/chassis.hpp
++++ b/redfish-core/lib/chassis.hpp
+@@ -429,9 +429,9 @@ inline void
+                 else if (interface ==
+                          "xyz.openbmc_project.Inventory.Decorator.LocationCode")
+                 {
+-                    location_util::getLocationCode(
+-                        asyncResp, connectionName, path,
+-                        "/Location"_json_pointer);
++                    location_util::getLocationCode(asyncResp, connectionName,
++                                                   path,
++                                                   "/Location"_json_pointer);
+                 }
+                 else if (location_util::isConnector(interface))
+                 {
+@@ -444,11 +444,21 @@ inline void
+                             << interface;
+                         continue;
+                     }
+-
++                    location_util::getPartLocationContext(
++                        asyncResp, "/Location"_json_pointer, path + "/chassis");
+                     asyncResp->res.jsonValue["Location"]["PartLocation"]
+                                             ["LocationType"] =
+                         *locationType;
+                 }
++                else if (interface ==
++                             "xyz.openbmc_project.Inventory.Item.Chassis" ||
++                         interface ==
++                             "xyz.openbmc_project.Inventory.Item.Board")
++                {
++                    location_util::getPartLocationContext(
++                        asyncResp, "/Location"_json_pointer,
++                        path + "/contained_by");
++                }
+             }
+ 
+             return;
diff --git a/recipes-phosphor/interfaces/bmcweb/0010-Storage-Add-PartLocationContext-in-storage.patch b/recipes-phosphor/interfaces/bmcweb/0010-Storage-Add-PartLocationContext-in-storage.patch
new file mode 100644
index 0000000..8b8d067
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0010-Storage-Add-PartLocationContext-in-storage.patch
@@ -0,0 +1,54 @@
+From 6c98bc651d26b766c34a1445d5dbe632d1a148c5 Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Mon, 8 May 2023 22:19:37 +0000
+Subject: [PATCH] Storage: Add PartLocationContext in storage
+
+Implements https://github.com/DMTF/Redfish/pull/5481
+
+Tested:
+Redfish validator not run- Schema not released yet. Tested wget
+
+{
+  "@odata.id": "/redfish/v1/Chassis/chassis0/Drives/drive0",
+  "@odata.type": "#Drive.v1_7_0.Drive",
+  "Id": "drive0",
+  "Links": {
+    "Chassis": {
+      "@odata.id": "/redfish/v1/Chassis/chassis0"
+    }
+  },
+  "Name": "drive0",
+  "PhysicalLocation": {
+    "PartLocation": {
+      "LocationType": "Embedded"
+    },
+    "PartLocationContext": "PE0"
+  },
+  "Status": {
+    "State": "Enabled"
+  }
+
+Patch Tracking Bug: b/281935694
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62839
+Upstream-Status: Submitted
+Justification: For Devpath3 implementation
+
+Change-Id: I7b78dc75b8c6cc8ca18762b63c08df9a93c973a0
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/lib/storage.hpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
+index 047d34a7..b2ba89a8 100644
+--- a/redfish-core/lib/storage.hpp
++++ b/redfish-core/lib/storage.hpp
+@@ -553,6 +553,8 @@ static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+         else if (interface == "xyz.openbmc_project.Inventory.Item.Drive")
+         {
+             getDriveItemProperties(asyncResp, connectionName, path);
++            location_util::getPartLocationContext(
++                asyncResp, "/PhysicalLocation"_json_pointer, path + "/chassis");
+         }
+         else if (interface ==
+                  "xyz.openbmc_project.Inventory.Decorator.LocationCode")
diff --git a/recipes-phosphor/interfaces/bmcweb/0012-chassis-Set-Chassis.Reset-to-support-only-RackMount-.patch b/recipes-phosphor/interfaces/bmcweb/0012-chassis-Set-Chassis.Reset-to-support-only-RackMount-.patch
index 7ddabb4..1cf0050 100644
--- a/recipes-phosphor/interfaces/bmcweb/0012-chassis-Set-Chassis.Reset-to-support-only-RackMount-.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0012-chassis-Set-Chassis.Reset-to-support-only-RackMount-.patch
@@ -1,4 +1,4 @@
-From c4f1e9ac1c9018d4324af9e35ae8c5ef32d2f8b0 Mon Sep 17 00:00:00 2001
+From 68727acab031fb8ce8fe62b311941a3376f96b7f Mon Sep 17 00:00:00 2001
 From: Willy Tu <wltu@google.com>
 Date: Thu, 29 Jul 2021 11:31:54 -0700
 Subject: [PATCH] chassis: Set Chassis.Reset to support only RackMount
@@ -91,26 +91,27 @@
 
 Change-Id: I9f512816607d5c21a8ea63d91d4f22bc11844b91
 Signed-off-by: Willy Tu <wltu@google.com>
+
 ---
- redfish-core/lib/chassis.hpp | 310 +++++++++++++++++++++++++++++++----
- 1 file changed, 282 insertions(+), 28 deletions(-)
+ redfish-core/lib/chassis.hpp | 307 +++++++++++++++++++++++++++++++----
+ 1 file changed, 279 insertions(+), 28 deletions(-)
 
 diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
-index da1bbf47..c567423b 100644
+index 8b64faa0..35c8ea54 100644
 --- a/redfish-core/lib/chassis.hpp
 +++ b/redfish-core/lib/chassis.hpp
 @@ -31,6 +31,7 @@
  #include <utils/location_utils.hpp>
-
+ 
  #include <array>
 +#include <functional>
  #include <string_view>
-
+ 
  namespace redfish
 @@ -295,6 +296,126 @@ inline void requestRoutesChassisCollection(App& app)
              std::bind_front(handleChassisCollectionGet, std::ref(app)));
  }
-
+ 
 +inline std::optional<std::string>
 +    getChassisTypeProperty(const std::variant<std::string>& property)
 +{
@@ -252,18 +253,16 @@
 @@ -548,6 +661,7 @@ inline void
                  getStorageLink(asyncResp, path);
                  });
-
+ 
 +            bool addedChassisResetAction = false;
              for (const auto& interface : interfaces2)
              {
                  if (interface == "xyz.openbmc_project.Common.UUID")
-@@ -577,6 +691,31 @@ inline void
-                                             ["LocationType"] =
-                         *locationType;
-                 }
-+                else if (interface == "xyz.openbmc_project."
-+                                      "Inventory.Item.Chassis")
-+                {
+@@ -586,9 +700,31 @@ inline void
+                     location_util::getPartLocationContext(
+                         asyncResp, "/Location"_json_pointer,
+                         path + "/contained_by");
++
 +                    getChassisType(
 +                        connectionName, path,
 +                        [asyncResp,
@@ -278,21 +277,23 @@
 +                                        getChassisTypeProperty(property));
 +                        });
 +                    addedChassisResetAction = true;
-+                }
-+            }
-+
+                 }
+             }
+ 
 +            // Item.Chassis interface is not available
 +            // Enable Reset Action by default.
 +            if (!addedChassisResetAction)
 +            {
 +                addChassisReset(asyncResp, chassisId, std::nullopt);
-             }
-
++            }
++
              return;
-@@ -782,29 +921,93 @@ inline void
+         }
+ 
+@@ -792,29 +928,93 @@ inline void
          });
  }
-
+ 
 -inline void handleChassisResetActionInfoPost(
 -    App& app, const crow::Request& req,
 +/**
@@ -365,10 +366,10 @@
          return;
      }
 -    BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
-
+ 
 -    std::string resetType;
 +    std::optional<std::string> chassisType = getChassisTypeProperty(property);
-
+ 
 -    if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
 +    if (chassisType && *chassisType != "RackMount" &&
 +        *chassisType != "StandAlone")
@@ -380,7 +381,7 @@
 +
          return;
      }
-
+ 
 -    if (resetType != "PowerCycle")
 +    if (resetType && *resetType != "PowerCycle")
      {
@@ -392,12 +393,12 @@
 +                         << *resetType;
 +        messages::actionParameterNotSupported(asyncResp->res, *resetType,
                                                "ResetType");
-
+ 
          return;
-@@ -812,6 +1015,25 @@ inline void handleChassisResetActionInfoPost(
+@@ -822,6 +1022,25 @@ inline void handleChassisResetActionInfoPost(
      doChassisPowerCycle(asyncResp);
  }
-
+ 
 +inline void handleChassisResetActionInfoPost(
 +    App& app, const crow::Request& req,
 +    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -420,10 +421,10 @@
  /**
   * ChassisResetAction class supports the POST method for the Reset
   * action.
-@@ -827,20 +1049,15 @@ inline void requestRoutesChassisResetAction(App& app)
+@@ -837,20 +1056,15 @@ inline void requestRoutesChassisResetAction(App& app)
              std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
  }
-
+ 
 -inline void handleChassisResetActionInfoGet(
 -    App& app, const crow::Request& req,
 +inline void validateChassisResetActionInfoHandler(
@@ -444,7 +445,7 @@
      asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
      nlohmann::json::array_t parameters;
      nlohmann::json::object_t parameter;
-@@ -849,12 +1066,49 @@ inline void handleChassisResetActionInfoGet(
+@@ -859,12 +1073,49 @@ inline void handleChassisResetActionInfoGet(
      parameter["DataType"] = "String";
      nlohmann::json::array_t allowed;
      allowed.push_back("PowerCycle");
@@ -476,7 +477,7 @@
 -
      asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
  }
-
+ 
 +inline void handleChassisResetActionInfoGet(
 +    App& app, const crow::Request& req,
 +    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -495,6 +496,3 @@
  /**
   * ChassisResetActionInfo derived class for delivering Chassis
   * ResetType AllowableValues using ResetInfo schema.
---
-2.40.0.634.g4ca3ef3211-goog
-
diff --git a/recipes-phosphor/interfaces/bmcweb/0017-Add-LocationCode-property-to-PCIe-slots.patch b/recipes-phosphor/interfaces/bmcweb/0017-Add-LocationCode-property-to-PCIe-slots.patch
index f1883fb..4c09f18 100644
--- a/recipes-phosphor/interfaces/bmcweb/0017-Add-LocationCode-property-to-PCIe-slots.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0017-Add-LocationCode-property-to-PCIe-slots.patch
@@ -33,12 +33,12 @@
 }
 
 Patch Tracking Bug: b/232023845
-Upstream info / review: https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/46591
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/63474
 Upstream-Status: Submitted
-Justification: Review upstream is abandoned
+Justification: Pending
 
-Signed-off-by: Jie Yang <jjy@google.com>
-Change-Id: I5edcfe0289892c15e71d72543e6d9eb90ab8cbab
+Change-Id: I7fc04dd577dace140d04a43fbbc5c28cf00aff17
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
 ---
  redfish-core/lib/pcie_slots.hpp | 63 +++++++++++++++++++++++++++++----
  1 file changed, 56 insertions(+), 7 deletions(-)
@@ -50,7 +50,7 @@
 @@ -20,6 +20,38 @@
  namespace redfish
  {
- 
+
 +inline void addLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
 +                        const std::string& connectionName,
 +                        const std::string& pcieSlotPath, bool findLocation,
@@ -99,12 +99,12 @@
 @@ -144,6 +177,8 @@ inline void
          slot["HotPluggable"] = *hotPluggable;
      }
- 
+
 +    // Pass the slot index to the callback.
 +    callback(slots.size());
      slots.emplace_back(std::move(slot));
  }
- 
+
 @@ -151,7 +186,7 @@ inline void onMapperAssociationDone(
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& chassisID, const std::string& pcieSlotPath,
@@ -130,11 +130,11 @@
 +                                             findLocation));
          });
  }
- 
+
 @@ -217,12 +256,17 @@ inline void
      asyncResp->res.jsonValue["Id"] = "1";
      asyncResp->res.jsonValue["Slots"] = nlohmann::json::array();
- 
+
 +    const std::string locationInterface =
 +        "xyz.openbmc_project.Inventory.Decorator."
 +        "LocationCode";
@@ -168,6 +168,6 @@
                  });
          }
      }
--- 
+--
 2.40.0.348.gf938b09366-goog
 
diff --git a/recipes-phosphor/interfaces/bmcweb/0017-Processor-Update-APIs-to-accept-json-pointer.patch b/recipes-phosphor/interfaces/bmcweb/0017-Processor-Update-APIs-to-accept-json-pointer.patch
index 194c711..8df63cd 100644
--- a/recipes-phosphor/interfaces/bmcweb/0017-Processor-Update-APIs-to-accept-json-pointer.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0017-Processor-Update-APIs-to-accept-json-pointer.patch
@@ -1,7 +1,7 @@
-From 2fa95228550abd69821020faaa4d5d7c6f6c1de8 Mon Sep 17 00:00:00 2001
+From dcff0347b725ddcc9d72546dd92e26a09e220b6e Mon Sep 17 00:00:00 2001
 From: Nikhil Namjoshi <nikhilnamjoshi@google.com>
 Date: Mon, 7 Nov 2022 18:33:05 +0000
-Subject: [PATCH 20/40] Processor: Update APIs to accept json pointer
+Subject: [PATCH] Processor: Update APIs to accept json pointer
 
 Tested:
     Redfish Validator Passed
@@ -58,15 +58,16 @@
 
 Change-Id: I7609293163157edcc307f33b4c7b844db47c72c5
 Signed-off-by: Nikhil Namjoshi <nikhilnamjoshi@google.com>
+
 ---
- redfish-core/lib/processor.hpp | 244 +++++++++++++++++++--------------
- 1 file changed, 138 insertions(+), 106 deletions(-)
+ redfish-core/lib/processor.hpp | 246 +++++++++++++++++++--------------
+ 1 file changed, 139 insertions(+), 107 deletions(-)
 
 diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp
-index 92a8ee10..5cba5feb 100644
+index bf027d38..be2b0579 100644
 --- a/redfish-core/lib/processor.hpp
 +++ b/redfish-core/lib/processor.hpp
-@@ -55,36 +55,39 @@ constexpr std::array<std::string_view, 2> processorInterfaces = {
+@@ -53,36 +53,39 @@ constexpr std::array<std::string_view, 2> processorInterfaces = {
   * @param[in,out]   aResp       Async HTTP response.
   * @param[in]       service     D-Bus service to query.
   * @param[in]       objPath     D-Bus object to query.
@@ -112,7 +113,7 @@
  
      for (const auto& interface : cpuInterfacesProperties)
      {
-@@ -102,7 +105,7 @@ inline void getCpuDataByInterface(
+@@ -100,7 +103,7 @@ inline void getCpuDataByInterface(
                  if (!*cpuPresent)
                  {
                      // Slot is not populated
@@ -121,7 +122,7 @@
                  }
              }
              else if (property.first == "Functional")
-@@ -115,7 +118,8 @@ inline void getCpuDataByInterface(
+@@ -113,7 +116,8 @@ inline void getCpuDataByInterface(
                  }
                  if (!*cpuFunctional)
                  {
@@ -131,7 +132,7 @@
                  }
              }
              else if (property.first == "CoreCount")
-@@ -127,14 +131,14 @@ inline void getCpuDataByInterface(
+@@ -125,14 +129,14 @@ inline void getCpuDataByInterface(
                      messages::internalError(aResp->res);
                      return;
                  }
@@ -148,7 +149,7 @@
                  }
              }
              else if (property.first == "Socket")
-@@ -143,7 +147,7 @@ inline void getCpuDataByInterface(
+@@ -141,7 +145,7 @@ inline void getCpuDataByInterface(
                      std::get_if<std::string>(&property.second);
                  if (value != nullptr)
                  {
@@ -157,7 +158,7 @@
                  }
              }
              else if (property.first == "ThreadCount")
-@@ -151,7 +155,7 @@ inline void getCpuDataByInterface(
+@@ -149,7 +153,7 @@ inline void getCpuDataByInterface(
                  const uint16_t* value = std::get_if<uint16_t>(&property.second);
                  if (value != nullptr)
                  {
@@ -166,7 +167,7 @@
                  }
              }
              else if (property.first == "EffectiveFamily")
-@@ -159,7 +163,8 @@ inline void getCpuDataByInterface(
+@@ -157,7 +161,8 @@ inline void getCpuDataByInterface(
                  const uint16_t* value = std::get_if<uint16_t>(&property.second);
                  if (value != nullptr && *value != 2)
                  {
@@ -176,7 +177,7 @@
                          "0x" + intToHexString(*value, 4);
                  }
              }
-@@ -173,7 +178,8 @@ inline void getCpuDataByInterface(
+@@ -171,7 +176,8 @@ inline void getCpuDataByInterface(
                  }
                  if (*value != 0)
                  {
@@ -186,7 +187,7 @@
                          "0x" + intToHexString(*value, 4);
                  }
              }
-@@ -182,8 +188,8 @@ inline void getCpuDataByInterface(
+@@ -180,8 +186,8 @@ inline void getCpuDataByInterface(
                  const uint64_t* value = std::get_if<uint64_t>(&property.second);
                  if (value != nullptr && *value != 0)
                  {
@@ -197,7 +198,7 @@
                          "0x" + intToHexString(*value, 16);
                  }
              }
-@@ -197,7 +203,8 @@ inline void getCpuDataByInterface(
+@@ -195,7 +201,8 @@ inline void getCpuDataByInterface(
                  }
                  if (*value != 0)
                  {
@@ -207,7 +208,7 @@
                          "0x" + intToHexString(*value, 8);
                  }
              }
-@@ -211,7 +218,7 @@ inline void getCpuDataByInterface(
+@@ -209,7 +216,7 @@ inline void getCpuDataByInterface(
                  }
                  if (*value != std::numeric_limits<uint16_t>::max())
                  {
@@ -216,7 +217,7 @@
                          "0x" + intToHexString(*value, 4);
                  }
              }
-@@ -222,12 +229,13 @@ inline void getCpuDataByInterface(
+@@ -220,12 +227,13 @@ inline void getCpuDataByInterface(
  inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
                                  const std::string& cpuId,
                                  const std::string& service,
@@ -232,7 +233,7 @@
              const boost::system::error_code& ec,
              const dbus::utility::ManagedObjectType& dbusData) {
          if (ec)
-@@ -236,9 +244,9 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -234,9 +242,9 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
              messages::internalError(aResp->res);
              return;
          }
@@ -245,7 +246,7 @@
  
          bool slotPresent = false;
          std::string corePath = objPath + "/core";
-@@ -247,7 +255,7 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -245,7 +253,7 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
          {
              if (object.first.str == objPath)
              {
@@ -254,7 +255,7 @@
              }
              else if (object.first.str.starts_with(corePath))
              {
-@@ -283,10 +291,10 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -281,10 +289,10 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
              if (totalCores == 0)
              {
                  // Slot is not populated, set status end return
@@ -268,7 +269,7 @@
          }
          return;
          },
-@@ -296,13 +304,14 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -294,13 +302,14 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
  
  inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp,
                              const std::string& service,
@@ -285,7 +286,7 @@
              const boost::system::error_code& ec,
              const dbus::utility::DBusPropertiesMap& properties) {
          if (ec)
-@@ -331,52 +340,54 @@ inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -329,52 +338,54 @@ inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp,
  
          if (serialNumber != nullptr && !serialNumber->empty())
          {
@@ -351,7 +352,7 @@
              const boost::system::error_code& ec,
              const dbus::utility::DBusPropertiesMap& properties) {
          if (ec)
-@@ -399,20 +410,21 @@ inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
+@@ -397,20 +408,21 @@ inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
  
          if (version != nullptr)
          {
@@ -376,7 +377,7 @@
              const boost::system::error_code& ec,
              const dbus::utility::DBusPropertiesMap& properties) {
          if (ec)
-@@ -451,11 +463,11 @@ inline void getAcceleratorDataByService(
+@@ -449,11 +461,11 @@ inline void getAcceleratorDataByService(
              }
          }
  
@@ -393,7 +394,7 @@
          });
  }
  
-@@ -471,12 +483,14 @@ using BaseSpeedPrioritySettingsProperty =
+@@ -469,12 +481,14 @@ using BaseSpeedPrioritySettingsProperty =
   * OperatingConfig D-Bus property.
   *
   * @param[in,out]   aResp               Async HTTP response.
@@ -408,7 +409,7 @@
      const BaseSpeedPrioritySettingsProperty& baseSpeedSettings)
  {
      // The D-Bus property does not indicate which bucket is the "high
-@@ -495,7 +509,8 @@ inline void highSpeedCoreIdsHandler(
+@@ -493,7 +507,8 @@ inline void highSpeedCoreIdsHandler(
          }
      }
  
@@ -418,7 +419,7 @@
      jsonCoreIds = nlohmann::json::array();
  
      // There may not be any entries in the D-Bus property, so only populate
-@@ -514,11 +529,13 @@ inline void highSpeedCoreIdsHandler(
+@@ -512,11 +527,13 @@ inline void highSpeedCoreIdsHandler(
   * @param[in]       cpuId       CPU D-Bus name.
   * @param[in]       service     D-Bus service to query.
   * @param[in]       objPath     D-Bus object to query.
@@ -433,7 +434,7 @@
  {
      BMCWEB_LOG_INFO << "Getting CPU operating configs for " << cpuId;
  
-@@ -526,7 +543,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -524,7 +541,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
      sdbusplus::asio::getAllProperties(
          *crow::connections::systemBus, service, objPath,
          "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig",
@@ -442,7 +443,7 @@
           service](const boost::system::error_code& ec,
                    const dbus::utility::DBusPropertiesMap& properties) {
          if (ec)
-@@ -559,7 +576,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -557,7 +574,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
              operatingConfig["@odata.id"] = crow::utility::urlFromPieces(
                  "redfish", "v1", "Systems", "system", "Processors", cpuId,
                  "OperatingConfigs");
@@ -451,7 +452,7 @@
  
              // Reuse the D-Bus config object name for the Redfish
              // URI
-@@ -577,7 +594,8 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -575,7 +592,8 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
              appliedOperatingConfig["@odata.id"] = crow::utility::urlFromPieces(
                  "redfish", "v1", "Systems", "system", "Processors", cpuId,
                  "OperatingConfigs", dbusPath.substr(baseNamePos + 1));
@@ -461,7 +462,7 @@
  
              // Once we found the current applied config, queue another
              // request to read the base freq core ids out of that
-@@ -587,7 +605,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -585,7 +603,7 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                  "xyz.openbmc_project.Inventory.Item.Cpu."
                  "OperatingConfig",
                  "BaseSpeedPrioritySettings",
@@ -470,7 +471,7 @@
                      const boost::system::error_code& ec2,
                      const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
                  if (ec2)
-@@ -597,13 +615,13 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -595,13 +613,13 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                      return;
                  }
  
@@ -486,7 +487,7 @@
                  *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
          }
          });
-@@ -616,39 +634,44 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -614,39 +632,44 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
   * @param[in,out]   aResp       Async HTTP response.
   * @param[in]       service     D-Bus service to query.
   * @param[in]       objPath     D-Bus object to query.
@@ -538,7 +539,7 @@
          if (ec)
          {
              return;
-@@ -671,7 +694,7 @@ inline void getCpuChassisAssociation(
+@@ -669,7 +692,7 @@ inline void getCpuChassisAssociation(
              BMCWEB_LOG_ERROR << "filename() is empty in " << chassisPath.str;
              return;
          }
@@ -547,7 +548,7 @@
              {"@odata.id", "/redfish/v1/Chassis/" + chassisName}};
          });
  }
-@@ -758,6 +781,7 @@ inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
+@@ -754,6 +777,7 @@ inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
  }
  
  inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
@@ -555,7 +556,7 @@
                               const std::string& processorId,
                               const std::string& objectPath,
                               const dbus::utility::MapperServiceMap& serviceMap)
-@@ -765,10 +789,10 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -761,10 +785,10 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
      aResp->res.addHeader(
          boost::beast::http::field::link,
          "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
@@ -569,7 +570,7 @@
          crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                       "Processors", processorId,
                                       "SubProcessors");
-@@ -778,44 +802,45 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -774,46 +798,47 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
          {
              if (interface == "xyz.openbmc_project.Inventory.Decorator.Asset")
              {
@@ -609,6 +610,9 @@
                  location_util::getLocationCode(aResp, serviceName, objectPath,
 -                                               "/Location"_json_pointer);
 +                                               jsonPtr / "Location");
+                 location_util::getPartLocationContext(
+-                    aResp, "/Location"_json_pointer, objectPath + "/chassis");
++                    aResp, jsonPtr / "Location", objectPath + "/chassis");
              }
              else if (interface == "xyz.openbmc_project.Common.UUID")
              {
@@ -623,7 +627,7 @@
              }
              else
              {
-@@ -830,12 +855,12 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+@@ -828,12 +853,12 @@ inline void getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                  }
  
                  aResp->res
@@ -639,7 +643,7 @@
  }
  
  template <typename Handler>
-@@ -950,19 +975,20 @@ inline void
+@@ -948,19 +973,20 @@ inline void
  
  inline void getCoreThreadDataByService(
      const std::shared_ptr<bmcweb::AsyncResp>& aResp,
@@ -668,7 +672,7 @@
  
      bool present = false;
      bool functional = false;
-@@ -1009,7 +1035,7 @@ inline void getCoreThreadDataByService(
+@@ -1007,7 +1033,7 @@ inline void getCoreThreadDataByService(
                          messages::internalError(aResp->res);
                          return;
                      }
@@ -677,7 +681,7 @@
                  }
              }
          }
-@@ -1025,7 +1051,8 @@ inline void getCoreThreadDataByService(
+@@ -1023,7 +1049,8 @@ inline void getCoreThreadDataByService(
                          messages::internalError(aResp->res);
                          return;
                      }
@@ -687,7 +691,7 @@
                          "0x" + intToHexString(*value, 8);
                  }
              }
-@@ -1034,12 +1061,12 @@ inline void getCoreThreadDataByService(
+@@ -1032,12 +1059,12 @@ inline void getCoreThreadDataByService(
  
      if (!present)
      {
@@ -702,7 +706,7 @@
      }
  }
  
-@@ -1119,7 +1146,8 @@ inline void getSubProcessorThreadData(
+@@ -1117,7 +1144,8 @@ inline void getSubProcessorThreadData(
                          continue;
                      }
  
@@ -712,7 +716,7 @@
                                                 threadId, interfaces);
                      return;
                  }
-@@ -1189,24 +1217,26 @@ inline void getSubProcessorThreadMembers(
+@@ -1187,24 +1215,26 @@ inline void getSubProcessorThreadMembers(
  
  inline void
      getCpuCoreDataByService(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
@@ -746,7 +750,7 @@
  
      bool present = false;
      bool functional = false;
-@@ -1253,7 +1283,7 @@ inline void
+@@ -1251,7 +1281,7 @@ inline void
                          messages::internalError(aResp->res);
                          return;
                      }
@@ -755,7 +759,7 @@
                  }
              }
          }
-@@ -1269,7 +1299,8 @@ inline void
+@@ -1267,7 +1297,8 @@ inline void
                          messages::internalError(aResp->res);
                          return;
                      }
@@ -765,7 +769,7 @@
                          "0x" + intToHexString(*value, 8);
                  }
              }
-@@ -1278,12 +1309,12 @@ inline void
+@@ -1276,12 +1307,12 @@ inline void
  
      if (!present)
      {
@@ -780,7 +784,7 @@
      }
  }
  
-@@ -1362,7 +1393,8 @@ inline void getSubProcessorCoreData(
+@@ -1360,7 +1391,8 @@ inline void getSubProcessorCoreData(
                          continue;
                      }
  
@@ -790,7 +794,7 @@
                                              interfaces);
                      return;
                  }
-@@ -1950,9 +1982,9 @@ inline void requestRoutesProcessor(App& app)
+@@ -1948,9 +1980,9 @@ inline void requestRoutesProcessor(App& app)
              return;
          }
  
@@ -803,6 +807,3 @@
          });
  
      BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
--- 
-2.40.0.348.gf938b09366-goog
-
diff --git a/recipes-phosphor/interfaces/bmcweb/0018-Add-presence-to-pcie-slots.patch b/recipes-phosphor/interfaces/bmcweb/0018-Add-presence-to-pcie-slots.patch
index a5b5537..36720c4 100644
--- a/recipes-phosphor/interfaces/bmcweb/0018-Add-presence-to-pcie-slots.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0018-Add-presence-to-pcie-slots.patch
@@ -1,4 +1,4 @@
-From 024c2a115dd893babf5c3b347f4530457da8b6c8 Mon Sep 17 00:00:00 2001
+From 0983d2c89f01bea6ec22f6da61a71ffff2df2542 Mon Sep 17 00:00:00 2001
 From: Cody Smith <scody@google.com>
 Date: Thu, 10 Mar 2022 21:31:56 +0000
 Subject: [PATCH] Add presence to pcie-slots
@@ -25,12 +25,13 @@
 
 Signed-off-by: Cody Smith <scody@google.com>
 Change-Id: I902bc29b762df7fa76208cd3dfc6f6f65c235f8b
+
 ---
  redfish-core/lib/pcie_slots.hpp | 66 +++++++++++++++++++++++++--------
  1 file changed, 51 insertions(+), 15 deletions(-)
 
 diff --git a/redfish-core/lib/pcie_slots.hpp b/redfish-core/lib/pcie_slots.hpp
-index cee08c0d..fd16eb3a 100644
+index 9d5d83bf..da5f68d1 100644
 --- a/redfish-core/lib/pcie_slots.hpp
 +++ b/redfish-core/lib/pcie_slots.hpp
 @@ -20,16 +20,38 @@
@@ -76,10 +77,10 @@
 -        return;
 -    }
 -
-     crow::connections::systemBus->async_method_call(
-         [asyncResp, index](const boost::system::error_code ec,
-                            const std::variant<std::string>& property) {
-@@ -186,7 +208,8 @@ inline void onMapperAssociationDone(
+     location_util::getPartLocationContext(
+         asyncResp, "/Slots"_json_pointer / index / "Location",
+         pcieSlotPath + "/chassis");
+@@ -190,7 +212,8 @@ inline void onMapperAssociationDone(
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& chassisID, const std::string& pcieSlotPath,
      const std::string& connectionName, const boost::system::error_code& ec,
@@ -89,7 +90,7 @@
  {
      if (ec)
      {
-@@ -218,13 +241,22 @@ inline void onMapperAssociationDone(
+@@ -222,13 +245,22 @@ inline void onMapperAssociationDone(
      sdbusplus::asio::getAllProperties(
          *crow::connections::systemBus, connectionName, pcieSlotPath,
          "xyz.openbmc_project.Inventory.Item.PCIeSlot",
@@ -117,7 +118,7 @@
          });
  }
  
-@@ -259,6 +291,7 @@ inline void
+@@ -263,6 +295,7 @@ inline void
      const std::string locationInterface =
          "xyz.openbmc_project.Inventory.Decorator."
          "LocationCode";
@@ -125,7 +126,7 @@
      for (const auto& pathServicePair : subtree)
      {
          const std::string& pcieSlotPath = pathServicePair.first;
-@@ -276,15 +309,18 @@ inline void
+@@ -280,15 +313,18 @@ inline void
              dbus::utility::getAssociationEndPoints(
                  std::string{pcieSlotAssociationPath},
                  [asyncResp, chassisID, pcieSlotPath, connectionName,
@@ -146,6 +147,3 @@
                  });
          }
      }
--- 
-2.40.0.348.gf938b09366-goog
-
diff --git a/recipes-phosphor/interfaces/bmcweb/0020-Add-LocationType-and-LocationCode-support-for-Cable.patch b/recipes-phosphor/interfaces/bmcweb/0020-Add-LocationType-and-LocationCode-support-for-Cable.patch
index 1eb3c61..34b61d2 100644
--- a/recipes-phosphor/interfaces/bmcweb/0020-Add-LocationType-and-LocationCode-support-for-Cable.patch
+++ b/recipes-phosphor/interfaces/bmcweb/0020-Add-LocationType-and-LocationCode-support-for-Cable.patch
@@ -24,12 +24,12 @@
 ```
 
 Patch Tracking Bug: b/232026681
-Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/52532
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/63476
 Upstream-Status: Submitted
 Justification: Pending upstream review
 
-Change-Id: I73c70ac5bd68fdf842a2dd4219855301cd21ab1b
-Signed-off-by: Zhenwei Chen <zhenweichen0207@gmail.com>
+Change-Id: I1df66c5f98ff841ca73160c51b9705ebc017f6d0
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
 ---
  redfish-core/lib/cable.hpp | 41 ++++++++++++++++++++++++++++----------
  1 file changed, 31 insertions(+), 10 deletions(-)
@@ -43,7 +43,7 @@
  #include "utils/dbus_utils.hpp"
  #include "utils/json_utils.hpp"
 +#include "utils/location_utils.hpp"
- 
+
  #include <boost/system/error_code.hpp>
  #include <sdbusplus/asio/property.hpp>
 @@ -128,19 +129,39 @@ inline void
@@ -80,7 +80,7 @@
 +                                     << interface;
 +                    continue;
 +                }
- 
+
 -            sdbusplus::asio::getAllProperties(
 -                *crow::connections::systemBus, service, cableObjectPath,
 -                interface,
@@ -96,6 +96,6 @@
          }
      }
  }
--- 
+--
 2.40.0.348.gf938b09366-goog
 
diff --git a/recipes-phosphor/interfaces/bmcweb/0036-Add-PartLocationContext-to-PCIe-Slots.patch b/recipes-phosphor/interfaces/bmcweb/0036-Add-PartLocationContext-to-PCIe-Slots.patch
new file mode 100644
index 0000000..25ad35c
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0036-Add-PartLocationContext-to-PCIe-Slots.patch
@@ -0,0 +1,52 @@
+From 68b98675915ea1518c41f9a15eb7f3934d28a05d Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Thu, 11 May 2023 03:50:43 +0000
+Subject: [PATCH] Add PartLocationContext to PCIe Slots
+
+Example PCIeSlots redfish resource:
+{
+  "@odata.id": "/redfish/v1/Chassis/GSZ/PCIeSlots",
+  "@odata.type": "#PCIeSlots.v1_4_1.PCIeSlots",
+  "Id": "PCIeSlots",
+  "Name": "PCIe Slot Information",
+  "Slots": [
+    {
+      "HotPluggable": false,
+      "Lanes": 16,
+      "Location": {
+        "PartLocation": {
+          "ServiceLabel": "PE0"
+        },
+        "PartLocationContext" : "PEX"
+      },
+      "PCIeType": "Gen5"
+    }
+  ]
+}
+
+Patch Tracking Bug: b/281936413
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/63475
+Upstream-Status: Submitted
+Justification: Required for Devpath3 implementation
+
+Change-Id: I8cd52b23f5958308908f765c87f99239182b280d
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/lib/pcie_slots.hpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/redfish-core/lib/pcie_slots.hpp b/redfish-core/lib/pcie_slots.hpp
+index cee08c0d..9d5d83bf 100644
+--- a/redfish-core/lib/pcie_slots.hpp
++++ b/redfish-core/lib/pcie_slots.hpp
+@@ -30,6 +30,10 @@ inline void addLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+         return;
+     }
+
++    location_util::getPartLocationContext(
++        asyncResp, "/Slots"_json_pointer / index / "Location",
++        pcieSlotPath + "/chassis");
++
+     crow::connections::systemBus->async_method_call(
+         [asyncResp, index](const boost::system::error_code ec,
+                            const std::variant<std::string>& property) {
diff --git a/recipes-phosphor/interfaces/bmcweb/0040-Cables-Add-PartLocationContext-to-cables.patch b/recipes-phosphor/interfaces/bmcweb/0040-Cables-Add-PartLocationContext-to-cables.patch
new file mode 100644
index 0000000..4a9ec24
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0040-Cables-Add-PartLocationContext-to-cables.patch
@@ -0,0 +1,60 @@
+From 6837f09cee196c68435e665f950aced0b4371524 Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Thu, 11 May 2023 03:29:59 +0000
+Subject: [PATCH] Cables: Add PartLocationContext to cables
+
+Implements https://github.com/DMTF/Redfish/pull/5481
+
+Tested:
+wget -qO- http://localhost/redfish/v1/Cables/NcsiCable
+{
+  "@odata.id": "/redfish/v1/Cables/NcsiCable",
+  "@odata.type": "#Cable.v1_0_0.Cable",
+  "Id": "NcsiCable",
+  "Links": {
+    "DownstreamChassis": [
+      {
+        "@odata.id": "/redfish/v1/Chassis/chassis_1"
+      }
+    ],
+    "UpstreamChassis": [
+      {
+         "@odata.id": "/redfish/v1/Chassis/chassis_0"
+      }
+    ]
+  },
+  "Location": {
+    "PartLocation": {
+      "LocationType": "Connector",
+      "ServiceLabel": "NCSI"
+    },
+    "PartLocationContext": "PEX"
+  },
+  "Name": "Cable"
+}
+
+Patch Tracking Bug: b/281936959
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/63477
+Upstream-Status: Submitted
+Justification: Required for Devpath3 implementation
+
+Change-Id: I0a2e29ca2c8e5fb15118c1d4477c6468fa0c54b8
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/lib/cable.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/redfish-core/lib/cable.hpp b/redfish-core/lib/cable.hpp
+index ae172fd0..083cb45e 100644
+--- a/redfish-core/lib/cable.hpp
++++ b/redfish-core/lib/cable.hpp
+@@ -146,6 +146,9 @@ inline void
+                 location_util::getLocationCode(asyncResp, service,
+                                                cableObjectPath,
+                                                "/Location"_json_pointer);
++                location_util::getPartLocationContext(
++                    asyncResp, "/Location"_json_pointer,
++                    cableObjectPath + "/upstream_chassis");
+             }
+             else if (location_util::isConnector(interface))
+             {
diff --git a/recipes-phosphor/interfaces/bmcweb/0042-Add-PartLocationContext-to-Assembly.patch b/recipes-phosphor/interfaces/bmcweb/0042-Add-PartLocationContext-to-Assembly.patch
new file mode 100644
index 0000000..4d1182d
--- /dev/null
+++ b/recipes-phosphor/interfaces/bmcweb/0042-Add-PartLocationContext-to-Assembly.patch
@@ -0,0 +1,75 @@
+From 00c02b2352c95e4fe40c5f621de9fe8d026389cb Mon Sep 17 00:00:00 2001
+From: Rahul Kapoor <rahulkpr@google.com>
+Date: Thu, 11 May 2023 02:51:39 +0000
+Subject: [PATCH] Add PartLocationContext to Assembly
+
+Tested:
+wget -qO- localhost/redfish/v1/Chassis/AgoraV2/Assembly
+{
+  "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly",
+  "@odata.type": "#Assembly.v1_3_0.Assembly",
+  "Assemblies": [
+    {
+      "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly#/Assemblies/0",
+      "@odata.type": "#Assembly.v1_3_0.AssemblyData",
+      "Location": {
+        "PartLocation": {
+          "LocationType": "Slot",
+          "ServiceLabel": "BIOS"
+        },
+        "PartLocationContext": "DC_SCM"
+      },
+      "MemberId": "0",
+      "Name": "BIOS_flash"
+    },
+    {
+      "@odata.id": "/redfish/v1/Chassis/AgoraV2/Assembly#/Assemblies/1",
+      "@odata.type": "#Assembly.v1_3_0.AssemblyData",
+      "Location": {
+        "PartLocation": {
+          "LocationType": "Slot",
+          "ServiceLabel": "BMC"
+        },
+        "PartLocationContext": "DC_SCM"
+      },
+      "MemberId": "1",
+      "Name": "BMC_flash"
+    }
+  ],
+  "Assemblies@odata.count": 2,
+  "Id": "Assembly",
+  "Name": "Assembly Collection"
+}
+
+Patch Tracking Bug: b/281937427
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/63478
+Upstream-Status: Submitted
+Justification: Required for Devpath3 implementation
+
+Change-Id: I16511ac76ac345e4940bc1632256261983f5b5ae
+Signed-off-by: Rahul Kapoor <rahulkpr@google.com>
+---
+ redfish-core/lib/assembly.hpp | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/redfish-core/lib/assembly.hpp b/redfish-core/lib/assembly.hpp
+index 961968de..45e5e348 100644
+--- a/redfish-core/lib/assembly.hpp
++++ b/redfish-core/lib/assembly.hpp
+@@ -146,10 +146,13 @@ inline void
+                         else if (interface == "xyz.openbmc_project.Inventory."
+                                               "Decorator.LocationCode")
+                         {
+-                            location_util::getLocationCode(
+-                                aResp, serviceName, assembly,
++                            nlohmann::json::json_pointer locationPtr =
+                                 "/Assemblies"_json_pointer / assemblyIndex /
+-                                    "Location");
++                                    "Location";
++                            location_util::getLocationCode(
++                                aResp, serviceName, assembly, locationPtr);
++                            location_util::getPartLocationContext(
++                                aResp, locationPtr, assembly + "/chassis");
+                         }
+                         else
+                         {
diff --git a/recipes-phosphor/interfaces/bmcweb_%.bbappend b/recipes-phosphor/interfaces/bmcweb_%.bbappend
index 416bf2f..fb9db2e 100644
--- a/recipes-phosphor/interfaces/bmcweb_%.bbappend
+++ b/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -13,10 +13,15 @@
 SRC_URI:append:gbmc = " \
   file://0001-Add-RDE-Device-aggregation-support.patch \
   file://0002-Add-dbus-interfaces-calls-to-RDEd.patch \
+  file://0001-Add-function-to-get-associated-chassis-subtree.patch \
   file://0001-location_utils-Add-helper-function-for-Location-and-.patch \
+  file://0003-location_utils-Implement-PartLocationContext.patch \
   file://0002-processor-Use-common-getLocationCode-for-Processor.patch \
+  file://0005-Processor-Add-PartLocationContext-in-Processor.patch \
   file://0003-manager-Use-common-getLocationCode-for-Manager.patch \
   file://0004-Add-LocationType-and-LocationCode-support-for-Chassi.patch \
+  file://0009-Chassis-Add-PartLocationContext-in-chassis.patch \
+  file://0010-Storage-Add-PartLocationContext-in-storage.patch \
   file://0005-Chassis-links-on-bmcweb.patch \
   file://0007-Add-Fan-mode-change-function.patch \
   file://service-override.conf \
@@ -53,10 +58,13 @@
   file://0017-Processor-Update-APIs-to-accept-json-pointer.patch \
   file://0018-Processor-Implement-Efficient-expand.patch \
   file://0017-Add-LocationCode-property-to-PCIe-slots.patch \
+  file://0036-Add-PartLocationContext-to-PCIe-Slots.patch \
   file://0018-Add-presence-to-pcie-slots.patch \
   file://0019-Links-of-Cable-and-Chassis-resource.patch \
   file://0020-Add-LocationType-and-LocationCode-support-for-Cable.patch \
+  file://0040-Cables-Add-PartLocationContext-to-cables.patch \
   file://0022-Implement-Inventory-properties-via-Assembly-schema.patch \
+  file://0042-Add-PartLocationContext-to-Assembly.patch \
   file://0025-json-utility-add-sort.patch \
   file://0026-Memory-implement-efficient-expand-handler.patch \
   file://0027-Links-of-Memory-resource.patch \