[dev][platform-bus] Add metadata support for children of platform devices
ZX-2500 #done
TEST: manual testing on VIM2 via another CL that will be out for review son.
Change-Id: Ibe873700a02bfd9baaadee6c25149b2c9f4990a6
diff --git a/system/dev/bus/platform/platform-device.cpp b/system/dev/bus/platform/platform-device.cpp
index 464cfaa..43680b3 100644
--- a/system/dev/bus/platform/platform-device.cpp
+++ b/system/dev/bus/platform/platform-device.cpp
@@ -248,6 +248,36 @@
return ZX_OK;
}
+zx_status_t PlatformDevice::RpcGetMetadata(const DeviceResources* dr, uint32_t index,
+ uint8_t* out_metadata, uint32_t* out_metadata_type,
+ uint32_t* out_metadata_length) {
+ if (index >= dr->metadata_count()) {
+ return ZX_ERR_OUT_OF_RANGE;
+ }
+ auto& metadata = dr->metadata(index);
+ if (metadata.data && metadata.len) {
+ if (metadata.len > PROXY_MAX_METADATA_SIZE) {
+ return ZX_ERR_BUFFER_TOO_SMALL;
+ }
+ memcpy(out_metadata, metadata.data, metadata.len);
+ *out_metadata_type = metadata.type;
+ *out_metadata_length = metadata.len;
+ return ZX_OK;
+ } else {
+ const void* data;
+ uint32_t length;
+ auto status = GetZbiMetadata(metadata.type, metadata.extra, &data, &length);
+ if (status == ZX_OK) {
+ if (length > PROXY_MAX_METADATA_SIZE) {
+ return ZX_ERR_BUFFER_TOO_SMALL;
+ }
+ memcpy(out_metadata, data, length);
+ *out_metadata_length = length;
+ }
+ return status;
+ }
+}
+
zx_status_t PlatformDevice::RpcUmsSetMode(const DeviceResources* dr, usb_mode_t mode) {
if (bus_->ums() == nullptr) {
return ZX_ERR_NOT_SUPPORTED;
@@ -507,6 +537,13 @@
case PDEV_DEVICE_ADD:
status = RpcDeviceAdd(dr, req->index, &resp->device_id);
break;
+ case PDEV_GET_METADATA: {
+ auto metadata = reinterpret_cast<uint8_t*>(&resp[1]);
+ status = RpcGetMetadata(dr, req->index, metadata, &resp->metadata_type,
+ &resp->metadata_length);
+ resp_len += static_cast<uint32_t>(resp->metadata_length * sizeof(*metadata));
+ break;
+ }
default:
zxlogf(ERROR, "platform_dev_rxrpc: unknown op %u\n", req_header->op);
return ZX_ERR_INTERNAL;
@@ -702,9 +739,8 @@
delete this;
}
-zx_status_t PlatformDevice::AddMetaData(const pbus_metadata_t& pbm) {
- const uint32_t type = pbm.type;
- const uint32_t extra = pbm.extra;
+zx_status_t PlatformDevice::GetZbiMetadata(uint32_t type, uint32_t extra, const void** out_metadata,
+ uint32_t* out_size) {
const uint8_t* metadata = bus_->metadata();
const size_t metadata_size = bus_->metadata_size();
size_t offset = 0;
@@ -714,7 +750,9 @@
size_t length = ZBI_ALIGN(sizeof(zbi_header_t) + header->length);
if (header->type == type && header->extra == extra) {
- return DdkAddMetadata(type, header + 1, length - sizeof(zbi_header_t));
+ *out_metadata = header + 1;
+ *out_size = static_cast<uint32_t>(length - sizeof(zbi_header_t));
+ return ZX_OK;
}
metadata += length;
offset += length;
@@ -762,7 +800,12 @@
if (pbm.data && pbm.len) {
status = DdkAddMetadata(pbm.type, pbm.data, pbm.len);
} else {
- status = AddMetaData(pbm);
+ const void* data;
+ uint32_t length;
+ status = GetZbiMetadata(pbm.type, pbm.extra, &data, &length);
+ if (status == ZX_OK) {
+ status = DdkAddMetadata(pbm.type, data, length);
+ }
}
if (status != ZX_OK) {
DdkRemove();
diff --git a/system/dev/bus/platform/platform-device.h b/system/dev/bus/platform/platform-device.h
index 1731c2f..4817079 100644
--- a/system/dev/bus/platform/platform-device.h
+++ b/system/dev/bus/platform/platform-device.h
@@ -86,6 +86,8 @@
zx_status_t RpcGetBti(const DeviceResources* dr, uint32_t index, zx_handle_t* out_handle,
uint32_t* out_handle_count);
zx_status_t RpcDeviceAdd(const DeviceResources* dr, uint32_t index, uint32_t* out_device_id);
+ zx_status_t RpcGetMetadata(const DeviceResources* dr, uint32_t index, uint8_t* out_metadata,
+ uint32_t* out_metadata_type, uint32_t* out_metadata_length);
zx_status_t RpcUmsSetMode(const DeviceResources* dr, usb_mode_t mode);
zx_status_t RpcGpioConfig(const DeviceResources* dr, uint32_t index, uint32_t flags);
zx_status_t RpcGpioSetAltFunction(const DeviceResources* dr, uint32_t index, uint64_t function);
@@ -112,7 +114,8 @@
zx_status_t RpcClkEnable(const DeviceResources* dr, uint32_t index);
zx_status_t RpcClkDisable(const DeviceResources* dr, uint32_t index);
- zx_status_t AddMetaData(const pbus_metadata_t& pbm);
+ zx_status_t GetZbiMetadata(uint32_t type, uint32_t extra, const void** out_metadata,
+ uint32_t* out_size);
PlatformBus* bus_;
char name_[ZX_DEVICE_NAME_MAX + 1];
diff --git a/system/dev/bus/platform/platform-proxy-device.cpp b/system/dev/bus/platform/platform-proxy-device.cpp
index 33480eb..cd5aed0 100644
--- a/system/dev/bus/platform/platform-proxy-device.cpp
+++ b/system/dev/bus/platform/platform-proxy-device.cpp
@@ -470,62 +470,58 @@
fbl::AllocChecker ac;
- if (info.mmio_count) {
- for (uint32_t i = 0; i < info.mmio_count; i++) {
- rpc_pdev_req_t req = {};
- rpc_pdev_rsp_t resp = {};
- zx_handle_t rsrc_handle;
+ for (uint32_t i = 0; i < info.mmio_count; i++) {
+ rpc_pdev_req_t req = {};
+ rpc_pdev_rsp_t resp = {};
+ zx_handle_t rsrc_handle;
- req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
- req.header.op = PDEV_GET_MMIO;
- req.index = i;
- status = proxy_->Rpc(device_id_, &req.header, sizeof(req), &resp.header, sizeof(resp),
- NULL, 0, &rsrc_handle, 1, NULL);
- if (status != ZX_OK) {
- return status;
- }
-
- Mmio mmio;
- mmio.base = resp.paddr;
- mmio.length = resp.length;
- mmio.resource.reset(rsrc_handle);
- mmios_.push_back(fbl::move(mmio), &ac);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
-
- zxlogf(SPEW, "%s: received MMIO %u (base %#lx length %#lx handle %#x)\n", name_, i,
- mmio.base, mmio.length, mmio.resource.get());
+ req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
+ req.header.op = PDEV_GET_MMIO;
+ req.index = i;
+ status = proxy_->Rpc(device_id_, &req.header, sizeof(req), &resp.header, sizeof(resp),
+ NULL, 0, &rsrc_handle, 1, NULL);
+ if (status != ZX_OK) {
+ return status;
}
+
+ Mmio mmio;
+ mmio.base = resp.paddr;
+ mmio.length = resp.length;
+ mmio.resource.reset(rsrc_handle);
+ mmios_.push_back(fbl::move(mmio), &ac);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ zxlogf(SPEW, "%s: received MMIO %u (base %#lx length %#lx handle %#x)\n", name_, i,
+ mmio.base, mmio.length, mmio.resource.get());
}
- if (info.irq_count) {
- for (uint32_t i = 0; i < info.irq_count; i++) {
- rpc_pdev_req_t req = {};
- rpc_pdev_rsp_t resp = {};
- zx_handle_t rsrc_handle;
+ for (uint32_t i = 0; i < info.irq_count; i++) {
+ rpc_pdev_req_t req = {};
+ rpc_pdev_rsp_t resp = {};
+ zx_handle_t rsrc_handle;
- req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
- req.header.op = PDEV_GET_INTERRUPT;
- req.index = i;
- status = proxy_->Rpc(device_id_, &req.header, sizeof(req), &resp.header, sizeof(resp),
- NULL, 0, &rsrc_handle, 1, NULL);
- if (status != ZX_OK) {
- return status;
- }
-
- Irq irq;
- irq.irq = resp.irq;
- irq.mode = resp.mode;
- irq.resource.reset(rsrc_handle);
- irqs_.push_back(fbl::move(irq), &ac);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
-
- zxlogf(SPEW, "%s: received IRQ %u (irq %#x handle %#x)\n", name_, i, irq.irq,
- irq.resource.get());
+ req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
+ req.header.op = PDEV_GET_INTERRUPT;
+ req.index = i;
+ status = proxy_->Rpc(device_id_, &req.header, sizeof(req), &resp.header, sizeof(resp),
+ NULL, 0, &rsrc_handle, 1, NULL);
+ if (status != ZX_OK) {
+ return status;
}
+
+ Irq irq;
+ irq.irq = resp.irq;
+ irq.mode = resp.mode;
+ irq.resource.reset(rsrc_handle);
+ irqs_.push_back(fbl::move(irq), &ac);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ zxlogf(SPEW, "%s: received IRQ %u (irq %#x handle %#x)\n", name_, i, irq.irq,
+ irq.resource.get());
}
if (args) {
@@ -534,7 +530,42 @@
proto_id_ = args->proto_id;
proto_ops_ = args->proto_ops;
- return DdkAdd(args->name, args->flags, args->props, args->prop_count);
+ if (info.metadata_count == 0) {
+ return DdkAdd(args->name, args->flags, args->props, args->prop_count);
+ }
+
+ auto status = DdkAdd(args->name, args->flags | DEVICE_ADD_INVISIBLE, args->props,
+ args->prop_count);
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ for (uint32_t i = 0; i < info.metadata_count; i++) {
+ rpc_pdev_req_t req = {};
+ struct {
+ rpc_pdev_rsp_t pdev;
+ uint8_t metadata[PROXY_MAX_METADATA_SIZE];
+ } resp = {};
+ req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
+ req.header.op = PDEV_GET_METADATA;
+ req.index = i;
+
+ status = proxy_->Rpc(device_id_, &req.header, sizeof(req), &resp.pdev.header,
+ sizeof(resp));
+ if (status != ZX_OK) {
+ DdkRemove();
+ return status;
+ }
+ status = DdkAddMetadata(resp.pdev.metadata_type, resp.metadata,
+ resp.pdev.metadata_length);
+ if (status != ZX_OK) {
+ DdkRemove();
+ return status;
+ }
+ }
+
+ DdkMakeVisible();
+ return ZX_OK;
} else {
return DdkAdd(name_);
}
diff --git a/system/dev/bus/platform/proxy-protocol.h b/system/dev/bus/platform/proxy-protocol.h
index 195a23c..d04b141 100644
--- a/system/dev/bus/platform/proxy-protocol.h
+++ b/system/dev/bus/platform/proxy-protocol.h
@@ -41,6 +41,7 @@
PDEV_GET_DEVICE_INFO,
PDEV_GET_BOARD_INFO,
PDEV_DEVICE_ADD,
+ PDEV_GET_METADATA,
};
typedef struct {
@@ -58,6 +59,8 @@
pdev_device_info_t device_info;
pdev_board_info_t board_info;
uint32_t device_id;
+ uint32_t metadata_type;
+ uint32_t metadata_length;
} rpc_pdev_rsp_t;
// Maximum I2C transfer is I2C_MAX_TRANSFER_SIZE minus size of largest header.
@@ -65,6 +68,9 @@
(sizeof(rpc_pdev_req_t) > sizeof(rpc_pdev_rsp_t) ?
sizeof(rpc_pdev_req_t) : sizeof(rpc_pdev_rsp_t)));
+// Maximum metadata size that can be returned via PDEV_DEVICE_GET_METADATA.
+static constexpr size_t PROXY_MAX_METADATA_SIZE = (PROXY_MAX_TRANSFER_SIZE - sizeof(rpc_pdev_rsp_t));
+
// ZX_PROTOCOL_USB_MODE_SWITCH proxy support.
enum {
UMS_SET_MODE,
diff --git a/system/ulib/ddk/include/ddk/protocol/platform-bus.h b/system/ulib/ddk/include/ddk/protocol/platform-bus.h
index 55f2137..17f291d 100644
--- a/system/ulib/ddk/include/ddk/protocol/platform-bus.h
+++ b/system/ulib/ddk/include/ddk/protocol/platform-bus.h
@@ -46,7 +46,7 @@
uint32_t type; // metadata type (matches zbi_header_t.type for bootloader metadata)
uint32_t extra; // matches zbi_header_t.extra for bootloader metadata
const void* data; // pointer to metadata (set to NULL for bootloader metadata)
- size_t len; // metadata length in bytes (set to zero for bootloader metadata)
+ uint32_t len; // metadata length in bytes (set to zero for bootloader metadata)
} pbus_metadata_t;
typedef struct pbus_dev pbus_dev_t;