+#if defined(__i386__) || defined(__x86_64__)
+
+#define DBGLOG 1
+
+#include <architecture/i386/pio.h>
+
+/* standard port addresses */
+enum {
+ COM1_PORT_ADDR = 0x3f8,
+ COM2_PORT_ADDR = 0x2f8
+};
+
+/* UART register offsets */
+enum {
+ UART_RBR = 0, /* receive buffer Register (R) */
+ UART_THR = 0, /* transmit holding register (W) */
+ UART_DLL = 0, /* DLAB = 1, divisor latch (LSB) */
+ UART_IER = 1, /* interrupt enable register */
+ UART_DLM = 1, /* DLAB = 1, divisor latch (MSB) */
+ UART_IIR = 2, /* interrupt ident register (R) */
+ UART_FCR = 2, /* fifo control register (W) */
+ UART_LCR = 3, /* line control register */
+ UART_MCR = 4, /* modem control register */
+ UART_LSR = 5, /* line status register */
+ UART_MSR = 6, /* modem status register */
+ UART_SCR = 7 /* scratch register */
+};
+
+enum {
+ UART_LCR_8BITS = 0x03,
+ UART_LCR_DLAB = 0x80
+};
+
+enum {
+ UART_MCR_DTR = 0x01,
+ UART_MCR_RTS = 0x02,
+ UART_MCR_OUT1 = 0x04,
+ UART_MCR_OUT2 = 0x08,
+ UART_MCR_LOOP = 0x10
+};
+
+enum {
+ UART_LSR_DR = 0x01,
+ UART_LSR_OE = 0x02,
+ UART_LSR_PE = 0x04,
+ UART_LSR_FE = 0x08,
+ UART_LSR_THRE = 0x20
+};
+
+static void uart_putc(char c)
+{
+ while (!(inb(COM1_PORT_ADDR + UART_LSR) & UART_LSR_THRE))
+ {}
+ outb(COM1_PORT_ADDR + UART_THR, c);
+}
+
+static int debug_probe( void )
+{
+ /* Verify that the Scratch Register is accessible */
+ outb(COM1_PORT_ADDR + UART_SCR, 0x5a);
+ if (inb(COM1_PORT_ADDR + UART_SCR) != 0x5a) return false;
+ outb(COM1_PORT_ADDR + UART_SCR, 0xa5);
+ if (inb(COM1_PORT_ADDR + UART_SCR) != 0xa5) return false;
+ uart_putc('\n');
+ return true;
+}
+
+static void uart_puthex(uint64_t num)
+{
+ int bit;
+ char c;
+ bool leading = true;
+
+ for (bit = 60; bit >= 0; bit -= 4)
+ {
+ c = 0xf & (num >> bit);
+ if (c)
+ leading = false;
+ else if (leading)
+ continue;
+ if (c <= 9)
+ c += '0';
+ else
+ c+= 'a' - 10;
+ uart_putc(c);
+ }
+}
+
+static void debug_code(uint32_t code, uint64_t value)
+{
+ int bit;
+ char c;
+
+ if (!(kIOHibernateDebugRestoreLogs & gIOHibernateDebugFlags))
+ return;
+
+ for (bit = 24; bit >= 0; bit -= 8)
+ {
+ c = 0xFF & (code >> bit);
+ if (c)
+ uart_putc(c);
+ }
+ uart_putc('=');
+ uart_puthex(value);
+ uart_putc('\n');
+ uart_putc('\r');
+}
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#if !defined(DBGLOG)
+#define debug_probe() (false)
+#define debug_code(c, v) {}
+#endif
+
+enum
+{
+ kIOHibernateRestoreCodeImageStart = 'imgS',
+ kIOHibernateRestoreCodeImageEnd = 'imgE',
+ kIOHibernateRestoreCodePageIndexStart = 'pgiS',
+ kIOHibernateRestoreCodePageIndexEnd = 'pgiE',
+ kIOHibernateRestoreCodeMapStart = 'mapS',
+ kIOHibernateRestoreCodeMapEnd = 'mapE',
+ kIOHibernateRestoreCodeWakeMapSize = 'wkms',
+ kIOHibernateRestoreCodeConflictPage = 'cfpg',
+ kIOHibernateRestoreCodeConflictSource = 'cfsr',
+ kIOHibernateRestoreCodeNoMemory = 'nomm'
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+static void fatal(void)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ outb(0xcf9, 6);
+#else
+ while (true) {}
+#endif
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+