diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 569d85c11a..7ccb6ceb4f 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -13,6 +13,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/units.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "cpu.h"
 #include "hw/arm/bcm2836.h"
@@ -29,8 +30,67 @@
 #define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
 #define SPINTABLE_ADDR  0xd8 /* Pi 3 bootloader spintable */
 
-/* Table of Linux board IDs for different Pi versions */
-static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
+enum BoardIdManufacturer {
+    M_SONY_UK = 0,
+    M_EMBEST = 2,
+};
+
+enum BoardIdChip {
+    C_BCM2835 = 0,
+    C_BCM2836 = 1,
+    C_BCM2837 = 2,
+};
+
+enum BoardIdType {
+    T_2B = 0x04,
+    T_3B = 0x08,
+};
+
+enum BoardIdRevision {
+    R_1_0 = 0,
+    R_1_1 = 1,
+    R_1_2 = 2,
+    R_1_3 = 3,
+};
+
+static const char *processor_typename[] = {
+    [C_BCM2836] = TYPE_BCM2836,
+    [C_BCM2837] = TYPE_BCM2837,
+};
+
+typedef struct BoardInfo BoardInfo;
+
+struct BoardInfo {
+    /* Table of Linux board IDs for different Pi versions */
+    int board_id;
+    /*
+     * Board revision codes:
+     * www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/
+     */
+    struct {
+        enum BoardIdType type;
+        enum BoardIdRevision revision;
+        enum BoardIdChip chip;
+        enum BoardIdManufacturer manufacturer;
+    } board_rev;
+    uint64_t ram_size_min;
+    uint64_t ram_size_max;
+};
+
+static const BoardInfo bcm283x_boards[] = {
+    [2] = {
+        .board_id = 0xc43,
+        .board_rev = { T_2B, R_1_1, C_BCM2836, M_EMBEST },
+        .ram_size_min = 1 * GiB,
+        .ram_size_max = 1 * GiB,
+    },
+    [3] = {
+        .board_id = 0xc44,
+        .board_rev = { T_3B, R_1_2, C_BCM2837, M_SONY_UK },
+        .ram_size_min = 1 * GiB,
+        .ram_size_max = 1 * GiB,
+    },
+};
 
 typedef struct RasPiState {
     BCM283XState soc;
@@ -116,7 +176,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
     static struct arm_boot_info binfo;
     int r;
 
-    binfo.board_id = raspi_boardid[version];
+    binfo.board_id = bcm283x_boards[version].board_id;
     binfo.ram_size = ram_size;
     binfo.nb_cpus = machine->smp.cpus;
 
@@ -148,7 +208,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
      * the normal Linux boot process
      */
     if (machine->firmware) {
-        hwaddr firmware_addr = version == 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2;
+        hwaddr firmware_addr = version >= 3 ? FIRMWARE_ADDR_3 : FIRMWARE_ADDR_2;
         /* load the firmware image (typically kernel.img) */
         r = load_image_targphys(machine->firmware, firmware_addr,
                                 ram_size - firmware_addr);
@@ -172,16 +232,32 @@ static void raspi_init(MachineState *machine, int version)
     BlockBackend *blk;
     BusState *bus;
     DeviceState *carddev;
+    char *size_str;
+    int board_rev;
+    const char *soc_type;
 
-    if (machine->ram_size > 1 * GiB) {
+    if (machine->ram_size < bcm283x_boards[version].ram_size_min) {
+        size_str = size_to_str(bcm283x_boards[version].ram_size_min);
+        error_report("Requested ram size is too small for this machine: "
+                     "minimum is %s", size_str);
+        g_free(size_str);
+        exit(1);
+    }
+    if (machine->ram_size > bcm283x_boards[version].ram_size_max) {
+        size_str = size_to_str(bcm283x_boards[version].ram_size_max);
         error_report("Requested ram size is too large for this machine: "
-                     "maximum is 1GB");
+                     "maximum is %s", size_str);
+        g_free(size_str);
+        exit(1);
+    }
+    if (!is_power_of_2(machine->ram_size)) {
+        error_report("Requested ram size is not a power of 2");
         exit(1);
     }
 
+    soc_type = processor_typename[bcm283x_boards[version].board_rev.chip];
     object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
-                            version == 3 ? TYPE_BCM2837 : TYPE_BCM2836,
-                            &error_abort, NULL);
+                            soc_type, &error_abort, NULL);
 
     /* Allocate and map RAM */
     memory_region_allocate_system_memory(&s->ram, OBJECT(machine), "ram",
@@ -192,9 +268,14 @@ static void raspi_init(MachineState *machine, int version)
                                    &error_abort);
     object_property_set_int(OBJECT(&s->soc), machine->smp.cpus, "enabled-cpus",
                             &error_abort);
-    int board_rev = version == 3 ? 0xa02082 : 0xa21041;
-    object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
-                            &error_abort);
+
+    board_rev = ((63 - clz64(machine->ram_size / MiB)) << 20)
+                | (bcm283x_boards[version].board_rev.manufacturer << 16)
+                | (bcm283x_boards[version].board_rev.chip << 12)
+                | (bcm283x_boards[version].board_rev.type << 4)
+                | (bcm283x_boards[version].board_rev.revision << 0);
+    object_property_set_int(OBJECT(&s->soc), board_rev,
+                            "board-rev", &error_abort);
     object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);
 
     /* Create and plug in the SD cards */
@@ -221,7 +302,7 @@ static void raspi2_init(MachineState *machine)
 
 static void raspi2_machine_init(MachineClass *mc)
 {
-    mc->desc = "Raspberry Pi 2";
+    mc->desc = "Raspberry Pi 2B";
     mc->init = raspi2_init;
     mc->block_default_type = IF_SD;
     mc->no_parallel = 1;
@@ -243,7 +324,7 @@ static void raspi3_init(MachineState *machine)
 
 static void raspi3_machine_init(MachineClass *mc)
 {
-    mc->desc = "Raspberry Pi 3";
+    mc->desc = "Raspberry Pi 3B";
     mc->init = raspi3_init;
     mc->block_default_type = IF_SD;
     mc->no_parallel = 1;
