1 /* 2 * Raspberry Pi emulation (c) 2012 Gregory Estrade 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 */ 7 8 #include "qemu/osdep.h" 9 #include "qapi/error.h" 10 #include "hw/misc/bcm2835_property.h" 11 #include "hw/qdev-properties.h" 12 #include "migration/vmstate.h" 13 #include "hw/irq.h" 14 #include "hw/misc/bcm2835_mbox_defs.h" 15 #include "hw/arm/raspberrypi-fw-defs.h" 16 #include "sysemu/dma.h" 17 #include "qemu/log.h" 18 #include "qemu/module.h" 19 #include "trace.h" 20 #include "hw/arm/raspi_platform.h" 21 22 #define VCHI_BUSADDR_SIZE sizeof(uint32_t) 23 24 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */ 25 26 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) 27 { 28 uint32_t tag; 29 uint32_t bufsize; 30 uint32_t tot_len; 31 size_t resplen; 32 uint32_t tmp; 33 int n; 34 uint32_t offset, length, color; 35 uint32_t start_num, number, otp_row; 36 37 /* 38 * Copy the current state of the framebuffer config; we will update 39 * this copy as we process tags and then ask the framebuffer to use 40 * it at the end. 41 */ 42 BCM2835FBConfig fbconfig = s->fbdev->config; 43 bool fbconfig_updated = false; 44 45 value &= ~0xf; 46 47 s->addr = value; 48 49 tot_len = ldl_le_phys(&s->dma_as, value); 50 51 /* @(addr + 4) : Buffer response code */ 52 value = s->addr + 8; 53 while (value + 8 <= s->addr + tot_len) { 54 tag = ldl_le_phys(&s->dma_as, value); 55 bufsize = ldl_le_phys(&s->dma_as, value + 4); 56 /* @(value + 8) : Request/response indicator */ 57 resplen = 0; 58 switch (tag) { 59 case RPI_FWREQ_PROPERTY_END: 60 break; 61 case RPI_FWREQ_GET_FIRMWARE_REVISION: 62 stl_le_phys(&s->dma_as, value + 12, 346337); 63 resplen = 4; 64 break; 65 case RPI_FWREQ_GET_BOARD_MODEL: 66 qemu_log_mask(LOG_UNIMP, 67 "bcm2835_property: 0x%08x get board model NYI\n", 68 tag); 69 resplen = 4; 70 break; 71 case RPI_FWREQ_GET_BOARD_REVISION: 72 stl_le_phys(&s->dma_as, value + 12, s->board_rev); 73 resplen = 4; 74 break; 75 case RPI_FWREQ_GET_BOARD_MAC_ADDRESS: 76 resplen = sizeof(s->macaddr.a); 77 dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen, 78 MEMTXATTRS_UNSPECIFIED); 79 break; 80 case RPI_FWREQ_GET_BOARD_SERIAL: 81 qemu_log_mask(LOG_UNIMP, 82 "bcm2835_property: 0x%08x get board serial NYI\n", 83 tag); 84 resplen = 8; 85 break; 86 case RPI_FWREQ_GET_ARM_MEMORY: 87 /* base */ 88 stl_le_phys(&s->dma_as, value + 12, 0); 89 /* size */ 90 stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base); 91 resplen = 8; 92 break; 93 case RPI_FWREQ_GET_VC_MEMORY: 94 /* base */ 95 stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base); 96 /* size */ 97 stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size); 98 resplen = 8; 99 break; 100 case RPI_FWREQ_SET_POWER_STATE: 101 /* Assume that whatever device they asked for exists, 102 * and we'll just claim we set it to the desired state 103 */ 104 tmp = ldl_le_phys(&s->dma_as, value + 16); 105 stl_le_phys(&s->dma_as, value + 16, (tmp & 1)); 106 resplen = 8; 107 break; 108 109 /* Clocks */ 110 111 case RPI_FWREQ_GET_CLOCK_STATE: 112 stl_le_phys(&s->dma_as, value + 16, 0x1); 113 resplen = 8; 114 break; 115 116 case RPI_FWREQ_SET_CLOCK_STATE: 117 qemu_log_mask(LOG_UNIMP, 118 "bcm2835_property: 0x%08x set clock state NYI\n", 119 tag); 120 resplen = 8; 121 break; 122 123 case RPI_FWREQ_GET_CLOCK_RATE: 124 case RPI_FWREQ_GET_MAX_CLOCK_RATE: 125 case RPI_FWREQ_GET_MIN_CLOCK_RATE: 126 switch (ldl_le_phys(&s->dma_as, value + 12)) { 127 case RPI_FIRMWARE_EMMC_CLK_ID: 128 stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE); 129 break; 130 case RPI_FIRMWARE_UART_CLK_ID: 131 stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE); 132 break; 133 case RPI_FIRMWARE_CORE_CLK_ID: 134 stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE); 135 break; 136 default: 137 stl_le_phys(&s->dma_as, value + 16, 138 RPI_FIRMWARE_DEFAULT_CLK_RATE); 139 break; 140 } 141 resplen = 8; 142 break; 143 144 case RPI_FWREQ_GET_CLOCKS: 145 /* TODO: add more clock IDs if needed */ 146 stl_le_phys(&s->dma_as, value + 12, 0); 147 stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID); 148 resplen = 8; 149 break; 150 151 case RPI_FWREQ_SET_CLOCK_RATE: 152 case RPI_FWREQ_SET_MAX_CLOCK_RATE: 153 case RPI_FWREQ_SET_MIN_CLOCK_RATE: 154 qemu_log_mask(LOG_UNIMP, 155 "bcm2835_property: 0x%08x set clock rate NYI\n", 156 tag); 157 resplen = 8; 158 break; 159 160 /* Temperature */ 161 162 case RPI_FWREQ_GET_TEMPERATURE: 163 stl_le_phys(&s->dma_as, value + 16, 25000); 164 resplen = 8; 165 break; 166 167 case RPI_FWREQ_GET_MAX_TEMPERATURE: 168 stl_le_phys(&s->dma_as, value + 16, 99000); 169 resplen = 8; 170 break; 171 172 /* Frame buffer */ 173 174 case RPI_FWREQ_FRAMEBUFFER_ALLOCATE: 175 stl_le_phys(&s->dma_as, value + 12, fbconfig.base); 176 stl_le_phys(&s->dma_as, value + 16, 177 bcm2835_fb_get_size(&fbconfig)); 178 resplen = 8; 179 break; 180 case RPI_FWREQ_FRAMEBUFFER_RELEASE: 181 resplen = 0; 182 break; 183 case RPI_FWREQ_FRAMEBUFFER_BLANK: 184 resplen = 4; 185 break; 186 case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT: 187 case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT: 188 resplen = 8; 189 break; 190 case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT: 191 fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12); 192 fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16); 193 bcm2835_fb_validate_config(&fbconfig); 194 fbconfig_updated = true; 195 /* fall through */ 196 case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT: 197 stl_le_phys(&s->dma_as, value + 12, fbconfig.xres); 198 stl_le_phys(&s->dma_as, value + 16, fbconfig.yres); 199 resplen = 8; 200 break; 201 case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT: 202 fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12); 203 fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16); 204 bcm2835_fb_validate_config(&fbconfig); 205 fbconfig_updated = true; 206 /* fall through */ 207 case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT: 208 stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual); 209 stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual); 210 resplen = 8; 211 break; 212 case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH: 213 resplen = 4; 214 break; 215 case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH: 216 fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12); 217 bcm2835_fb_validate_config(&fbconfig); 218 fbconfig_updated = true; 219 /* fall through */ 220 case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH: 221 stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp); 222 resplen = 4; 223 break; 224 case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER: 225 resplen = 4; 226 break; 227 case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER: 228 fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12); 229 bcm2835_fb_validate_config(&fbconfig); 230 fbconfig_updated = true; 231 /* fall through */ 232 case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER: 233 stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo); 234 resplen = 4; 235 break; 236 case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE: 237 resplen = 4; 238 break; 239 case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE: 240 fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12); 241 bcm2835_fb_validate_config(&fbconfig); 242 fbconfig_updated = true; 243 /* fall through */ 244 case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE: 245 stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha); 246 resplen = 4; 247 break; 248 case RPI_FWREQ_FRAMEBUFFER_GET_PITCH: 249 stl_le_phys(&s->dma_as, value + 12, 250 bcm2835_fb_get_pitch(&fbconfig)); 251 resplen = 4; 252 break; 253 case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET: 254 resplen = 8; 255 break; 256 case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET: 257 fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12); 258 fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16); 259 bcm2835_fb_validate_config(&fbconfig); 260 fbconfig_updated = true; 261 /* fall through */ 262 case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET: 263 stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset); 264 stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset); 265 resplen = 8; 266 break; 267 case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN: 268 case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN: 269 case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN: 270 stl_le_phys(&s->dma_as, value + 12, 0); 271 stl_le_phys(&s->dma_as, value + 16, 0); 272 stl_le_phys(&s->dma_as, value + 20, 0); 273 stl_le_phys(&s->dma_as, value + 24, 0); 274 resplen = 16; 275 break; 276 case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE: 277 offset = ldl_le_phys(&s->dma_as, value + 12); 278 length = ldl_le_phys(&s->dma_as, value + 16); 279 n = 0; 280 while (n < length - offset) { 281 color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2)); 282 stl_le_phys(&s->dma_as, 283 s->fbdev->vcram_base + ((offset + n) << 2), color); 284 n++; 285 } 286 stl_le_phys(&s->dma_as, value + 12, 0); 287 resplen = 4; 288 break; 289 290 case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS: 291 stl_le_phys(&s->dma_as, value + 12, 1); 292 resplen = 4; 293 break; 294 295 case RPI_FWREQ_GET_DMA_CHANNELS: 296 /* channels 2-5 */ 297 stl_le_phys(&s->dma_as, value + 12, 0x003C); 298 resplen = 4; 299 break; 300 301 case RPI_FWREQ_GET_COMMAND_LINE: 302 /* 303 * We follow the firmware behaviour: no NUL terminator is 304 * written to the buffer, and if the buffer is too short 305 * we report the required length in the response header 306 * and copy nothing to the buffer. 307 */ 308 resplen = strlen(s->command_line); 309 if (bufsize >= resplen) 310 address_space_write(&s->dma_as, value + 12, 311 MEMTXATTRS_UNSPECIFIED, s->command_line, 312 resplen); 313 break; 314 315 case RPI_FWREQ_GET_THROTTLED: 316 stl_le_phys(&s->dma_as, value + 12, 0); 317 resplen = 4; 318 break; 319 320 case RPI_FWREQ_VCHIQ_INIT: 321 stl_le_phys(&s->dma_as, 322 value + offsetof(rpi_firmware_prop_request_t, payload), 323 0); 324 resplen = VCHI_BUSADDR_SIZE; 325 break; 326 327 /* Customer OTP */ 328 329 case RPI_FWREQ_GET_CUSTOMER_OTP: 330 start_num = ldl_le_phys(&s->dma_as, value + 12); 331 number = ldl_le_phys(&s->dma_as, value + 16); 332 333 resplen = 8 + 4 * number; 334 335 for (n = start_num; n < start_num + number && 336 n < BCM2835_OTP_CUSTOMER_OTP_LEN; n++) { 337 otp_row = bcm2835_otp_get_row(s->otp, 338 BCM2835_OTP_CUSTOMER_OTP + n); 339 stl_le_phys(&s->dma_as, 340 value + 20 + ((n - start_num) << 2), otp_row); 341 } 342 break; 343 case RPI_FWREQ_SET_CUSTOMER_OTP: 344 start_num = ldl_le_phys(&s->dma_as, value + 12); 345 number = ldl_le_phys(&s->dma_as, value + 16); 346 347 resplen = 4; 348 349 /* Magic numbers to permanently lock customer OTP */ 350 if (start_num == BCM2835_OTP_LOCK_NUM1 && 351 number == BCM2835_OTP_LOCK_NUM2) { 352 bcm2835_otp_set_row(s->otp, 353 BCM2835_OTP_ROW_32, 354 BCM2835_OTP_ROW_32_LOCK); 355 break; 356 } 357 358 /* If row 32 has the lock bit, don't allow further writes */ 359 if (bcm2835_otp_get_row(s->otp, BCM2835_OTP_ROW_32) & 360 BCM2835_OTP_ROW_32_LOCK) { 361 break; 362 } 363 364 for (n = start_num; n < start_num + number && 365 n < BCM2835_OTP_CUSTOMER_OTP_LEN; n++) { 366 otp_row = ldl_le_phys(&s->dma_as, 367 value + 20 + ((n - start_num) << 2)); 368 bcm2835_otp_set_row(s->otp, 369 BCM2835_OTP_CUSTOMER_OTP + n, otp_row); 370 } 371 break; 372 373 /* Device-specific private key */ 374 375 case RPI_FWREQ_GET_PRIVATE_KEY: 376 start_num = ldl_le_phys(&s->dma_as, value + 12); 377 number = ldl_le_phys(&s->dma_as, value + 16); 378 379 resplen = 8 + 4 * number; 380 381 for (n = start_num; n < start_num + number && 382 n < BCM2835_OTP_PRIVATE_KEY_LEN; n++) { 383 otp_row = bcm2835_otp_get_row(s->otp, 384 BCM2835_OTP_PRIVATE_KEY + n); 385 stl_le_phys(&s->dma_as, 386 value + 20 + ((n - start_num) << 2), otp_row); 387 } 388 break; 389 case RPI_FWREQ_SET_PRIVATE_KEY: 390 start_num = ldl_le_phys(&s->dma_as, value + 12); 391 number = ldl_le_phys(&s->dma_as, value + 16); 392 393 resplen = 4; 394 395 /* If row 32 has the lock bit, don't allow further writes */ 396 if (bcm2835_otp_get_row(s->otp, BCM2835_OTP_ROW_32) & 397 BCM2835_OTP_ROW_32_LOCK) { 398 break; 399 } 400 401 for (n = start_num; n < start_num + number && 402 n < BCM2835_OTP_PRIVATE_KEY_LEN; n++) { 403 otp_row = ldl_le_phys(&s->dma_as, 404 value + 20 + ((n - start_num) << 2)); 405 bcm2835_otp_set_row(s->otp, 406 BCM2835_OTP_PRIVATE_KEY + n, otp_row); 407 } 408 break; 409 default: 410 qemu_log_mask(LOG_UNIMP, 411 "bcm2835_property: unhandled tag 0x%08x\n", tag); 412 break; 413 } 414 415 trace_bcm2835_mbox_property(tag, bufsize, resplen); 416 if (tag == 0) { 417 break; 418 } 419 420 stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen); 421 value += bufsize + 12; 422 } 423 424 /* Reconfigure framebuffer if required */ 425 if (fbconfig_updated) { 426 bcm2835_fb_reconfigure(s->fbdev, &fbconfig); 427 } 428 429 /* Buffer response code */ 430 stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31)); 431 } 432 433 static uint64_t bcm2835_property_read(void *opaque, hwaddr offset, 434 unsigned size) 435 { 436 BCM2835PropertyState *s = opaque; 437 uint32_t res = 0; 438 439 switch (offset) { 440 case MBOX_AS_DATA: 441 res = MBOX_CHAN_PROPERTY | s->addr; 442 s->pending = false; 443 qemu_set_irq(s->mbox_irq, 0); 444 break; 445 446 case MBOX_AS_PENDING: 447 res = s->pending; 448 break; 449 450 default: 451 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 452 __func__, offset); 453 return 0; 454 } 455 456 return res; 457 } 458 459 static void bcm2835_property_write(void *opaque, hwaddr offset, 460 uint64_t value, unsigned size) 461 { 462 BCM2835PropertyState *s = opaque; 463 464 switch (offset) { 465 case MBOX_AS_DATA: 466 /* bcm2835_mbox should check our pending status before pushing */ 467 assert(!s->pending); 468 s->pending = true; 469 bcm2835_property_mbox_push(s, value); 470 qemu_set_irq(s->mbox_irq, 1); 471 break; 472 473 default: 474 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 475 __func__, offset); 476 return; 477 } 478 } 479 480 static const MemoryRegionOps bcm2835_property_ops = { 481 .read = bcm2835_property_read, 482 .write = bcm2835_property_write, 483 .endianness = DEVICE_NATIVE_ENDIAN, 484 .valid.min_access_size = 4, 485 .valid.max_access_size = 4, 486 }; 487 488 static const VMStateDescription vmstate_bcm2835_property = { 489 .name = TYPE_BCM2835_PROPERTY, 490 .version_id = 1, 491 .minimum_version_id = 1, 492 .fields = (const VMStateField[]) { 493 VMSTATE_MACADDR(macaddr, BCM2835PropertyState), 494 VMSTATE_UINT32(addr, BCM2835PropertyState), 495 VMSTATE_BOOL(pending, BCM2835PropertyState), 496 VMSTATE_END_OF_LIST() 497 } 498 }; 499 500 static void bcm2835_property_init(Object *obj) 501 { 502 BCM2835PropertyState *s = BCM2835_PROPERTY(obj); 503 504 memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s, 505 TYPE_BCM2835_PROPERTY, 0x10); 506 507 /* 508 * bcm2835_property_ops call into bcm2835_mbox, which in-turn reads from 509 * iomem. As such, mark iomem as re-entracy safe. 510 */ 511 s->iomem.disable_reentrancy_guard = true; 512 513 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); 514 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq); 515 } 516 517 static void bcm2835_property_reset(DeviceState *dev) 518 { 519 BCM2835PropertyState *s = BCM2835_PROPERTY(dev); 520 521 s->pending = false; 522 } 523 524 static void bcm2835_property_realize(DeviceState *dev, Error **errp) 525 { 526 BCM2835PropertyState *s = BCM2835_PROPERTY(dev); 527 Object *obj; 528 529 obj = object_property_get_link(OBJECT(dev), "fb", &error_abort); 530 s->fbdev = BCM2835_FB(obj); 531 532 obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort); 533 s->dma_mr = MEMORY_REGION(obj); 534 address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_PROPERTY "-memory"); 535 536 obj = object_property_get_link(OBJECT(dev), "otp", &error_abort); 537 s->otp = BCM2835_OTP(obj); 538 539 /* TODO: connect to MAC address of USB NIC device, once we emulate it */ 540 qemu_macaddr_default_if_unset(&s->macaddr); 541 542 bcm2835_property_reset(dev); 543 } 544 545 static Property bcm2835_property_props[] = { 546 DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0), 547 DEFINE_PROP_STRING("command-line", BCM2835PropertyState, command_line), 548 DEFINE_PROP_END_OF_LIST() 549 }; 550 551 static void bcm2835_property_class_init(ObjectClass *klass, void *data) 552 { 553 DeviceClass *dc = DEVICE_CLASS(klass); 554 555 device_class_set_props(dc, bcm2835_property_props); 556 dc->realize = bcm2835_property_realize; 557 dc->vmsd = &vmstate_bcm2835_property; 558 } 559 560 static const TypeInfo bcm2835_property_info = { 561 .name = TYPE_BCM2835_PROPERTY, 562 .parent = TYPE_SYS_BUS_DEVICE, 563 .instance_size = sizeof(BCM2835PropertyState), 564 .class_init = bcm2835_property_class_init, 565 .instance_init = bcm2835_property_init, 566 }; 567 568 static void bcm2835_property_register_types(void) 569 { 570 type_register_static(&bcm2835_property_info); 571 } 572 573 type_init(bcm2835_property_register_types) 574