hw/misc: Implement mailbox properties for customer OTP and device specific private keys
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. Bit 6 of row 32 indicates this lock, which is undocumented. The lock also applies to the device-specific private key. Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
6bf7993921
commit
5d5f1b6091
@ -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);
|
||||
|
@ -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,89 @@ 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 < BCM2835_OTP_CUSTOMER_OTP_LEN; n++) {
|
||||
otp_row = bcm2835_otp_get_row(s->otp,
|
||||
BCM2835_OTP_CUSTOMER_OTP + n);
|
||||
stl_le_phys(&s->dma_as,
|
||||
value + 20 + ((n - start_num) << 2), otp_row);
|
||||
}
|
||||
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 == BCM2835_OTP_LOCK_NUM1 &&
|
||||
number == BCM2835_OTP_LOCK_NUM2) {
|
||||
bcm2835_otp_set_row(s->otp,
|
||||
BCM2835_OTP_ROW_32,
|
||||
BCM2835_OTP_ROW_32_LOCK);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If row 32 has the lock bit, don't allow further writes */
|
||||
if (bcm2835_otp_get_row(s->otp, BCM2835_OTP_ROW_32) &
|
||||
BCM2835_OTP_ROW_32_LOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (n = start_num; n < start_num + number &&
|
||||
n < BCM2835_OTP_CUSTOMER_OTP_LEN; n++) {
|
||||
otp_row = ldl_le_phys(&s->dma_as,
|
||||
value + 20 + ((n - start_num) << 2));
|
||||
bcm2835_otp_set_row(s->otp,
|
||||
BCM2835_OTP_CUSTOMER_OTP + 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 < BCM2835_OTP_PRIVATE_KEY_LEN; n++) {
|
||||
otp_row = bcm2835_otp_get_row(s->otp,
|
||||
BCM2835_OTP_PRIVATE_KEY + n);
|
||||
stl_le_phys(&s->dma_as,
|
||||
value + 20 + ((n - start_num) << 2), otp_row);
|
||||
}
|
||||
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;
|
||||
|
||||
/* If row 32 has the lock bit, don't allow further writes */
|
||||
if (bcm2835_otp_get_row(s->otp, BCM2835_OTP_ROW_32) &
|
||||
BCM2835_OTP_ROW_32_LOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (n = start_num; n < start_num + number &&
|
||||
n < BCM2835_OTP_PRIVATE_KEY_LEN; n++) {
|
||||
otp_row = ldl_le_phys(&s->dma_as,
|
||||
value + 20 + ((n - start_num) << 2));
|
||||
bcm2835_otp_set_row(s->otp,
|
||||
BCM2835_OTP_PRIVATE_KEY + n, otp_row);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: unhandled tag 0x%08x\n", tag);
|
||||
@ -449,6 +533,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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user