Four mailbox properties are implemented as follows:
1. Customer OTP: GET_CUSTOMER_OTP and SET_CUSTOMER_OTP
2. Device-specific private key: GET_PRIVATE_KEY and
SET_PRIVATE_KEY.
The customer OTP is located in the rows 36-43. The device-specific private key
is located in the rows 56-63.
The customer OTP can be locked with the magic numbers 0xffffffff 0xaffe0000
when running the SET_CUSTOMER_OTP mailbox command.
P.S I am not sure if the magic lock combo applies to the private key as well.
Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com>
---
hw/arm/bcm2835_peripherals.c | 2 +
hw/misc/bcm2835_property.c | 71 ++++++++++++++++++++++++++++
include/hw/arm/raspberrypi-fw-defs.h | 2 +
include/hw/misc/bcm2835_property.h | 2 +
4 files changed, 77 insertions(+)
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 7d735bb56c..ac153a96b9 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -132,6 +132,8 @@ static void raspi_peripherals_base_init(Object *obj)
OBJECT(&s->fb));
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
OBJECT(&s->gpu_bus_mr));
+ object_property_add_const_link(OBJECT(&s->property), "otp",
+ OBJECT(&s->otp));
/* Extended Mass Media Controller */
object_initialize_child(obj, "sdhci", &s->sdhci, TYPE_SYSBUS_SDHCI);
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index bdd9a6bbce..bbd9c40af2 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -32,6 +32,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
uint32_t tmp;
int n;
uint32_t offset, length, color;
+ uint32_t start_num, number, otp_row;
/*
* Copy the current state of the framebuffer config; we will update
@@ -322,6 +323,73 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
0);
resplen = VCHI_BUSADDR_SIZE;
break;
+
+ /* Customer OTP */
+
+ case RPI_FWREQ_GET_CUSTOMER_OTP:
+ start_num = ldl_le_phys(&s->dma_as, value + 12);
+ number = ldl_le_phys(&s->dma_as, value + 16);
+
+ resplen = 8 + 4 * number;
+
+ for (n = start_num; n < start_num + number && n < 8; n++) {
+ stl_le_phys(&s->dma_as,
+ value + 20 + ((n - start_num) << 2),
+ bcm2835_otp_read_row(s->otp, 36 + n));
+ }
+ break;
+ case RPI_FWREQ_SET_CUSTOMER_OTP:
+ start_num = ldl_le_phys(&s->dma_as, value + 12);
+ number = ldl_le_phys(&s->dma_as, value + 16);
+
+ resplen = 4;
+
+ /* Magic numbers to permanently lock customer OTP */
+ if (start_num == 0xffffffff &&
+ number == 0xaffe0000) {
+ /* Row 30 Bit 30 indicates disabled OTP programming */
+ bcm2835_otp_write_row(s->otp, 30, 1 << 30);
+ break;
+ }
+
+ /* If customer OTP is locked, don't allow further writes */
+ if (bcm2835_otp_read_row(s->otp, 30) & (1 << 30)) {
+ break;
+ }
+
+ for (n = start_num; n < start_num + number && n < 8; n++) {
+ otp_row = ldl_le_phys(&s->dma_as,
+ value + 20 + ((n - start_num) << 2));
+ bcm2835_otp_write_row(s->otp, 36 + n, otp_row);
+ }
+ break;
+
+ /* Device-specific private key */
+
+ case RPI_FWREQ_GET_PRIVATE_KEY:
+ start_num = ldl_le_phys(&s->dma_as, value + 12);
+ number = ldl_le_phys(&s->dma_as, value + 16);
+
+ resplen = 8 + 4 * number;
+
+ for (n = start_num; n < start_num + number && n < 8; n++) {
+ stl_le_phys(&s->dma_as,
+ value + 20 + ((n - start_num) << 2),
+ bcm2835_otp_read_row(s->otp, 56 + n));
+ }
+ break;
+ case RPI_FWREQ_SET_PRIVATE_KEY:
+ start_num = ldl_le_phys(&s->dma_as, value + 12);
+ number = ldl_le_phys(&s->dma_as, value + 16);
+
+ resplen = 4;
+
+ for (n = start_num; n < start_num + number && n < 8; n++) {
+ otp_row = ldl_le_phys(&s->dma_as,
+ value + 20 + ((n - start_num) << 2));
+ bcm2835_otp_write_row(s->otp, 56 + n, otp_row);
+ }
+ break;
default:
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: unhandled tag 0x%08x\n", tag);
@@ -449,6 +517,9 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp)
s->dma_mr = MEMORY_REGION(obj);
address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_PROPERTY "-memory");
+ obj = object_property_get_link(OBJECT(dev), "otp", &error_abort);
+ s->otp = BCM2835_OTP(obj);
+
/* TODO: connect to MAC address of USB NIC device, once we emulate it */
qemu_macaddr_default_if_unset(&s->macaddr);
diff --git a/include/hw/arm/raspberrypi-fw-defs.h b/include/hw/arm/raspberrypi-fw-defs.h
index 8b404e0533..60b8e5b451 100644
--- a/include/hw/arm/raspberrypi-fw-defs.h
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -56,6 +56,7 @@ enum rpi_firmware_property_tag {
RPI_FWREQ_GET_THROTTLED = 0x00030046,
RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
+ RPI_FWREQ_GET_PRIVATE_KEY = 0x00030081,
RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
RPI_FWREQ_SET_VOLTAGE = 0x00038003,
@@ -73,6 +74,7 @@ enum rpi_firmware_property_tag {
RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
+ RPI_FWREQ_SET_PRIVATE_KEY = 0x00038081,
RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h
index ba8896610c..2f93fd0c75 100644
--- a/include/hw/misc/bcm2835_property.h
+++ b/include/hw/misc/bcm2835_property.h
@@ -11,6 +11,7 @@
#include "hw/sysbus.h"
#include "net/net.h"
#include "hw/display/bcm2835_fb.h"
+#include "hw/nvram/bcm2835_otp.h"
#include "qom/object.h"
#define TYPE_BCM2835_PROPERTY "bcm2835-property"
@@ -26,6 +27,7 @@ struct BCM2835PropertyState {
MemoryRegion iomem;
qemu_irq mbox_irq;
BCM2835FBState *fbdev;
+ BCM2835OTPState *otp;
MACAddr macaddr;
uint32_t board_rev;
--
2.34.1
On 10/5/24 16:10, Rayhan Faizel wrote: > Four mailbox properties are implemented as follows: > 1. Customer OTP: GET_CUSTOMER_OTP and SET_CUSTOMER_OTP > 2. Device-specific private key: GET_PRIVATE_KEY and > SET_PRIVATE_KEY. > > The customer OTP is located in the rows 36-43. The device-specific private key > is located in the rows 56-63. Better to define these instead of using magic values in the code, i.e.: #define OTP_PRIVATE_KEY_OFFSET 56 #define OTP_PRIVATE_KEY_LENGTH 8 > The customer OTP can be locked with the magic numbers 0xffffffff 0xaffe0000 > when running the SET_CUSTOMER_OTP mailbox command. > > P.S I am not sure if the magic lock combo applies to the private key as well. > > Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> > --- > hw/arm/bcm2835_peripherals.c | 2 + > hw/misc/bcm2835_property.c | 71 ++++++++++++++++++++++++++++ > include/hw/arm/raspberrypi-fw-defs.h | 2 + > include/hw/misc/bcm2835_property.h | 2 + > 4 files changed, 77 insertions(+) > + /* Device-specific private key */ > + > + case RPI_FWREQ_GET_PRIVATE_KEY: > + start_num = ldl_le_phys(&s->dma_as, value + 12); > + number = ldl_le_phys(&s->dma_as, value + 16); > + > + resplen = 8 + 4 * number; > + > + for (n = start_num; n < start_num + number && n < 8; n++) { > + stl_le_phys(&s->dma_as, > + value + 20 + ((n - start_num) << 2), > + bcm2835_otp_read_row(s->otp, 56 + n)); > + } > + break; > + case RPI_FWREQ_SET_PRIVATE_KEY: > + start_num = ldl_le_phys(&s->dma_as, value + 12); > + number = ldl_le_phys(&s->dma_as, value + 16); > + > + resplen = 4; > + > + for (n = start_num; n < start_num + number && n < 8; n++) { > + otp_row = ldl_le_phys(&s->dma_as, > + value + 20 + ((n - start_num) << 2)); > + bcm2835_otp_write_row(s->otp, 56 + n, otp_row); > + } > + break;
© 2016 - 2024 Red Hat, Inc.