|
@@ -69,7 +69,73 @@ void __hot romcopy_bzero(void *dst, size_t len)
|
|
|
ROMCOPY_DATALEN = len | ROMCOPY_ZERO_BUFFER | ROMCOPY_WRITE_RAM;
|
|
|
}
|
|
|
|
|
|
-static __hot void romcopy_config_flash(void)
|
|
|
+/*
|
|
|
+ * Read unique serial number programmed into ROM. Convert the serial
|
|
|
+ * number to 12 characters in base32; we lose four bits but that is never
|
|
|
+ * going to matter. It's more fun than plain hex... :)
|
|
|
+ *
|
|
|
+ * This is run before the 64-bit division routines are available in SDRAM,
|
|
|
+ * so it needs to be an encoding that can be generated with only plain
|
|
|
+ * 32-bit instructions.
|
|
|
+ *
|
|
|
+ * Doing this as early as possible means a much better chance to see
|
|
|
+ * the proper serial number during USB enumeration, so doing it
|
|
|
+ * immediately after SPI ROM conditioning is a great time.
|
|
|
+ */
|
|
|
+char __bss_hot rom_serial_str[16];
|
|
|
+qword_t __bss_hot rom_serial;
|
|
|
+
|
|
|
+static __must_inline void rom_read_serial(void)
|
|
|
+{
|
|
|
+ ROMCOPY_ROMCMD = ROM_READ_UNIQUE_ID << 24;
|
|
|
+ ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(5) | ROMCOPY_SPI_MORE;
|
|
|
+ waitfor(ROMCOPY_IRQ);
|
|
|
+
|
|
|
+ ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4) | ROMCOPY_SPI_MORE;
|
|
|
+ waitfor(ROMCOPY_IRQ);
|
|
|
+
|
|
|
+ rom_serial.l[1] = ROMCOPY_INPUT;
|
|
|
+ ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4);
|
|
|
+ waitfor(ROMCOPY_IRQ);
|
|
|
+
|
|
|
+ rom_serial.l[0] = ROMCOPY_INPUT;
|
|
|
+}
|
|
|
+
|
|
|
+static __must_inline void rom_mangle_serial(void)
|
|
|
+{
|
|
|
+ rom_serial_str[12] = '\0';
|
|
|
+ uint64_t v = rom_serial.q;
|
|
|
+
|
|
|
+ for (int i = 11; i >= 0; i--) {
|
|
|
+ unsigned char c;
|
|
|
+ unsigned int d = v & 31;
|
|
|
+ v >>= 5;
|
|
|
+
|
|
|
+ c = d + '0';
|
|
|
+ if (c > '9')
|
|
|
+ c += 'A'-'9'-1;
|
|
|
+ if (c >= 'I')
|
|
|
+ c++;
|
|
|
+ if (c >= 'O')
|
|
|
+ c++;
|
|
|
+ if (c >= 'S')
|
|
|
+ c++;
|
|
|
+
|
|
|
+ /* IOSZ not used to avoid confusion with 1052 */
|
|
|
+
|
|
|
+ rom_serial_str[i] = c;
|
|
|
+ usbdesc_rom[2+2*i] = c;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void rom_print_serial(void)
|
|
|
+{
|
|
|
+ /* Print the ROM serial when we actually can */
|
|
|
+ con_printf("ROM serial: %08x-%08x (%s)\n",
|
|
|
+ rom_serial.l[1], rom_serial.l[0], rom_serial_str);
|
|
|
+}
|
|
|
+
|
|
|
+static __must_inline void romcopy_config_flash(void)
|
|
|
{
|
|
|
/* Enable writing volatile status register bits */
|
|
|
ROMCOPY_ROMCMD = ROM_VOLATILE_SR_WRITE_ENABLE << 24;
|
|
@@ -82,24 +148,6 @@ static __hot void romcopy_config_flash(void)
|
|
|
waitfor(ROMCOPY_IRQ);
|
|
|
|
|
|
asm volatile("nop; nop"); /* Make extra sure tSHSL2 is OK */
|
|
|
-
|
|
|
- if ( 1 ) {
|
|
|
- con_puts(hotstr("ROM serial: "));
|
|
|
-
|
|
|
- ROMCOPY_ROMCMD = ROM_READ_UNIQUE_ID << 24;
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(5) | ROMCOPY_SPI_MORE;
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4) | ROMCOPY_SPI_MORE;
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- con_print_hex(ROMCOPY_INPUT);
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4);
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- con_print_hex(ROMCOPY_INPUT);
|
|
|
- con_putc('\n');
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
IRQHANDLER(romcopy,0)
|
|
@@ -109,11 +157,18 @@ IRQHANDLER(romcopy,0)
|
|
|
|
|
|
switch (romcopy_state++) {
|
|
|
case 0:
|
|
|
+ /* Condition flash ROM */
|
|
|
romcopy_config_flash();
|
|
|
|
|
|
- /* Copy DRAM data */
|
|
|
+ /* Read serial number */
|
|
|
+ rom_read_serial();
|
|
|
+
|
|
|
+ /* Start copy DRAM data */
|
|
|
len = __dram_init_end - __dram_init_start;
|
|
|
romcopy_download(__dram_init_start, 0, len);
|
|
|
+
|
|
|
+ /* Convert serial number and export to USB */
|
|
|
+ rom_mangle_serial();
|
|
|
break;
|
|
|
case 1:
|
|
|
/* Zero .dram.bss */
|
|
@@ -125,49 +180,3 @@ IRQHANDLER(romcopy,0)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-/*
|
|
|
- * Read unique serial number programmed into ROM. Convert the serial
|
|
|
- * number to 12 characters in base36 (technically a wraparound that is
|
|
|
- * never going to matter.) It's more fun than plain hex... :)
|
|
|
- */
|
|
|
-char __bss_hot serial_str[16];
|
|
|
-
|
|
|
-uint64_t __hot rom_get_serial(void)
|
|
|
-{
|
|
|
- union {
|
|
|
- uint32_t l[2];
|
|
|
- uint64_t q;
|
|
|
- } o;
|
|
|
-
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- ROMCOPY_ROMCMD = ROM_READ_UNIQUE_ID << 24;
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(5) | ROMCOPY_SPI_MORE;
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4) | ROMCOPY_SPI_MORE;
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- o.l[1] = ROMCOPY_INPUT;
|
|
|
- ROMCOPY_DATALEN = ROMCOPY_SPI_CMDLEN(4);
|
|
|
- waitfor(ROMCOPY_IRQ);
|
|
|
-
|
|
|
- o.l[0] = ROMCOPY_INPUT;
|
|
|
-
|
|
|
- serial_str[12] = '\0';
|
|
|
- uint64_t v = o.q;
|
|
|
- for (int i = 11; i >= 0; i--) {
|
|
|
- unsigned char c;
|
|
|
- unsigned int d = v % 36;
|
|
|
- v /= 36;
|
|
|
-
|
|
|
- c = d + '0' + ('A'-'0'-10)*(d >= 10);
|
|
|
- serial_str[i] = c;
|
|
|
- usbdesc_rom[2+2*i] = c;
|
|
|
- }
|
|
|
-
|
|
|
- con_printf("ROM serial: %08x-%08x (%s)\n", o.l[1], o.l[0], serial_str);
|
|
|
-
|
|
|
- return o.q;
|
|
|
-}
|